| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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 // MSVC++ requires this to be set before any other includes to get M_PI. | 5 // MSVC++ requires this to be set before any other includes to get M_PI. |
| 6 #define _USE_MATH_DEFINES | 6 #define _USE_MATH_DEFINES |
| 7 | 7 |
| 8 #include "ui/events/blink/blink_event_util.h" | 8 #include "ui/events/blink/blink_event_util.h" |
| 9 | 9 |
| 10 #include <stddef.h> | 10 #include <stddef.h> |
| 11 | 11 |
| 12 #include <algorithm> | 12 #include <algorithm> |
| 13 #include <bitset> |
| 13 #include <cmath> | 14 #include <cmath> |
| 15 #include <limits> |
| 14 | 16 |
| 15 #include "base/time/time.h" | 17 #include "base/time/time.h" |
| 16 #include "build/build_config.h" | 18 #include "build/build_config.h" |
| 17 #include "third_party/WebKit/public/platform/WebInputEvent.h" | 19 #include "third_party/WebKit/public/platform/WebInputEvent.h" |
| 18 #include "ui/events/base_event_utils.h" | 20 #include "ui/events/base_event_utils.h" |
| 19 #include "ui/events/event_constants.h" | 21 #include "ui/events/event_constants.h" |
| 20 #include "ui/events/gesture_detection/gesture_event_data.h" | 22 #include "ui/events/gesture_detection/gesture_event_data.h" |
| 21 #include "ui/events/gesture_detection/motion_event.h" | 23 #include "ui/events/gesture_detection/motion_event.h" |
| 22 #include "ui/events/gesture_event_details.h" | 24 #include "ui/events/gesture_event_details.h" |
| 23 #include "ui/events/keycodes/dom/keycode_converter.h" | 25 #include "ui/events/keycodes/dom/keycode_converter.h" |
| 24 #include "ui/gfx/geometry/safe_integer_conversions.h" | 26 #include "ui/gfx/geometry/safe_integer_conversions.h" |
| 25 #include "ui/gfx/geometry/vector2d.h" | 27 #include "ui/gfx/geometry/vector2d.h" |
| 26 | 28 |
| 27 using blink::WebGestureEvent; | 29 using blink::WebGestureEvent; |
| 28 using blink::WebInputEvent; | 30 using blink::WebInputEvent; |
| 31 using blink::WebMouseEvent; |
| 32 using blink::WebMouseWheelEvent; |
| 29 using blink::WebPointerProperties; | 33 using blink::WebPointerProperties; |
| 30 using blink::WebTouchEvent; | 34 using blink::WebTouchEvent; |
| 31 using blink::WebTouchPoint; | 35 using blink::WebTouchPoint; |
| 36 using std::numeric_limits; |
| 32 | 37 |
| 33 namespace ui { | 38 namespace ui { |
| 34 namespace { | 39 namespace { |
| 35 | 40 |
| 41 const int kInvalidTouchIndex = -1; |
| 42 |
| 36 WebInputEvent::Type ToWebInputEventType(MotionEvent::Action action) { | 43 WebInputEvent::Type ToWebInputEventType(MotionEvent::Action action) { |
| 37 switch (action) { | 44 switch (action) { |
| 38 case MotionEvent::ACTION_DOWN: | 45 case MotionEvent::ACTION_DOWN: |
| 39 return WebInputEvent::TouchStart; | 46 return WebInputEvent::TouchStart; |
| 40 case MotionEvent::ACTION_MOVE: | 47 case MotionEvent::ACTION_MOVE: |
| 41 return WebInputEvent::TouchMove; | 48 return WebInputEvent::TouchMove; |
| 42 case MotionEvent::ACTION_UP: | 49 case MotionEvent::ACTION_UP: |
| 43 return WebInputEvent::TouchEnd; | 50 return WebInputEvent::TouchEnd; |
| 44 case MotionEvent::ACTION_CANCEL: | 51 case MotionEvent::ACTION_CANCEL: |
| 45 return WebInputEvent::TouchCancel; | 52 return WebInputEvent::TouchCancel; |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 153 float z = cos(tilt_rad); | 160 float z = cos(tilt_rad); |
| 154 touch.tiltX = lround(atan2(sin(-orientation_rad) * r, z) * 180.f / M_PI); | 161 touch.tiltX = lround(atan2(sin(-orientation_rad) * r, z) * 180.f / M_PI); |
| 155 touch.tiltY = lround(atan2(cos(-orientation_rad) * r, z) * 180.f / M_PI); | 162 touch.tiltY = lround(atan2(cos(-orientation_rad) * r, z) * 180.f / M_PI); |
| 156 } else { | 163 } else { |
| 157 touch.tiltX = touch.tiltY = 0; | 164 touch.tiltX = touch.tiltY = 0; |
| 158 } | 165 } |
| 159 | 166 |
| 160 return touch; | 167 return touch; |
| 161 } | 168 } |
| 162 | 169 |
| 170 float GetUnacceleratedDelta(float accelerated_delta, float acceleration_ratio) { |
| 171 return accelerated_delta * acceleration_ratio; |
| 172 } |
| 173 |
| 174 float GetAccelerationRatio(float accelerated_delta, float unaccelerated_delta) { |
| 175 if (unaccelerated_delta == 0.f || accelerated_delta == 0.f) |
| 176 return 1.f; |
| 177 return unaccelerated_delta / accelerated_delta; |
| 178 } |
| 179 |
| 180 // Returns |kInvalidTouchIndex| iff |event| lacks a touch with an ID of |id|. |
| 181 int GetIndexOfTouchID(const WebTouchEvent& event, int id) { |
| 182 for (unsigned i = 0; i < event.touchesLength; ++i) { |
| 183 if (event.touches[i].id == id) |
| 184 return i; |
| 185 } |
| 186 return kInvalidTouchIndex; |
| 187 } |
| 188 |
| 189 WebInputEvent::DispatchType MergeDispatchTypes( |
| 190 WebInputEvent::DispatchType type_1, |
| 191 WebInputEvent::DispatchType type_2) { |
| 192 static_assert(WebInputEvent::DispatchType::Blocking < |
| 193 WebInputEvent::DispatchType::EventNonBlocking, |
| 194 "Enum not ordered correctly"); |
| 195 static_assert(WebInputEvent::DispatchType::EventNonBlocking < |
| 196 WebInputEvent::DispatchType::ListenersNonBlockingPassive, |
| 197 "Enum not ordered correctly"); |
| 198 static_assert( |
| 199 WebInputEvent::DispatchType::ListenersNonBlockingPassive < |
| 200 WebInputEvent::DispatchType::ListenersForcedNonBlockingDueToFling, |
| 201 "Enum not ordered correctly"); |
| 202 return static_cast<WebInputEvent::DispatchType>( |
| 203 std::min(static_cast<int>(type_1), static_cast<int>(type_2))); |
| 204 } |
| 205 |
| 206 bool CanCoalesce(const WebMouseEvent& event_to_coalesce, |
| 207 const WebMouseEvent& event) { |
| 208 return event.type == event_to_coalesce.type && |
| 209 event.type == WebInputEvent::MouseMove; |
| 210 } |
| 211 |
| 212 void Coalesce(const WebMouseEvent& event_to_coalesce, WebMouseEvent* event) { |
| 213 DCHECK(CanCoalesce(event_to_coalesce, *event)); |
| 214 // Accumulate movement deltas. |
| 215 int x = event->movementX; |
| 216 int y = event->movementY; |
| 217 *event = event_to_coalesce; |
| 218 event->movementX += x; |
| 219 event->movementY += y; |
| 220 } |
| 221 |
| 222 bool CanCoalesce(const WebMouseWheelEvent& event_to_coalesce, |
| 223 const WebMouseWheelEvent& event) { |
| 224 return event.modifiers == event_to_coalesce.modifiers && |
| 225 event.scrollByPage == event_to_coalesce.scrollByPage && |
| 226 event.phase == event_to_coalesce.phase && |
| 227 event.momentumPhase == event_to_coalesce.momentumPhase && |
| 228 event.hasPreciseScrollingDeltas == |
| 229 event_to_coalesce.hasPreciseScrollingDeltas; |
| 230 } |
| 231 |
| 232 void Coalesce(const WebMouseWheelEvent& event_to_coalesce, |
| 233 WebMouseWheelEvent* event) { |
| 234 DCHECK(CanCoalesce(event_to_coalesce, *event)); |
| 235 float unaccelerated_x = |
| 236 GetUnacceleratedDelta(event->deltaX, event->accelerationRatioX) + |
| 237 GetUnacceleratedDelta(event_to_coalesce.deltaX, |
| 238 event_to_coalesce.accelerationRatioX); |
| 239 float unaccelerated_y = |
| 240 GetUnacceleratedDelta(event->deltaY, event->accelerationRatioY) + |
| 241 GetUnacceleratedDelta(event_to_coalesce.deltaY, |
| 242 event_to_coalesce.accelerationRatioY); |
| 243 float old_deltaX = event->deltaX; |
| 244 float old_deltaY = event->deltaY; |
| 245 float old_wheelTicksX = event->wheelTicksX; |
| 246 float old_wheelTicksY = event->wheelTicksY; |
| 247 float old_movementX = event->movementX; |
| 248 float old_movementY = event->movementY; |
| 249 *event = event_to_coalesce; |
| 250 event->deltaX += old_deltaX; |
| 251 event->deltaY += old_deltaY; |
| 252 event->wheelTicksX += old_wheelTicksX; |
| 253 event->wheelTicksY += old_wheelTicksY; |
| 254 event->movementX += old_movementX; |
| 255 event->movementY += old_movementY; |
| 256 event->accelerationRatioX = |
| 257 GetAccelerationRatio(event->deltaX, unaccelerated_x); |
| 258 event->accelerationRatioY = |
| 259 GetAccelerationRatio(event->deltaY, unaccelerated_y); |
| 260 } |
| 261 |
| 262 bool CanCoalesce(const WebTouchEvent& event_to_coalesce, |
| 263 const WebTouchEvent& event) { |
| 264 if (event.type != event_to_coalesce.type || |
| 265 event.type != WebInputEvent::TouchMove || |
| 266 event.modifiers != event_to_coalesce.modifiers || |
| 267 event.touchesLength != event_to_coalesce.touchesLength || |
| 268 event.touchesLength > WebTouchEvent::kTouchesLengthCap) |
| 269 return false; |
| 270 |
| 271 static_assert(WebTouchEvent::kTouchesLengthCap <= sizeof(int32_t) * 8U, |
| 272 "suboptimal kTouchesLengthCap size"); |
| 273 // Ensure that we have a 1-to-1 mapping of pointer ids between touches. |
| 274 std::bitset<WebTouchEvent::kTouchesLengthCap> unmatched_event_touches( |
| 275 (1 << event.touchesLength) - 1); |
| 276 for (unsigned i = 0; i < event_to_coalesce.touchesLength; ++i) { |
| 277 int event_touch_index = |
| 278 GetIndexOfTouchID(event, event_to_coalesce.touches[i].id); |
| 279 if (event_touch_index == kInvalidTouchIndex) |
| 280 return false; |
| 281 if (!unmatched_event_touches[event_touch_index]) |
| 282 return false; |
| 283 unmatched_event_touches[event_touch_index] = false; |
| 284 } |
| 285 return unmatched_event_touches.none(); |
| 286 } |
| 287 |
| 288 void Coalesce(const WebTouchEvent& event_to_coalesce, WebTouchEvent* event) { |
| 289 DCHECK(CanCoalesce(event_to_coalesce, *event)); |
| 290 // The WebTouchPoints include absolute position information. So it is |
| 291 // sufficient to simply replace the previous event with the new event-> |
| 292 // However, it is necessary to make sure that all the points have the |
| 293 // correct state, i.e. the touch-points that moved in the last event, but |
| 294 // didn't change in the current event, will have Stationary state. It is |
| 295 // necessary to change them back to Moved state. |
| 296 WebTouchEvent old_event = *event; |
| 297 *event = event_to_coalesce; |
| 298 for (unsigned i = 0; i < event->touchesLength; ++i) { |
| 299 int i_old = GetIndexOfTouchID(old_event, event->touches[i].id); |
| 300 if (old_event.touches[i_old].state == blink::WebTouchPoint::StateMoved) |
| 301 event->touches[i].state = blink::WebTouchPoint::StateMoved; |
| 302 } |
| 303 event->movedBeyondSlopRegion |= old_event.movedBeyondSlopRegion; |
| 304 event->dispatchType = MergeDispatchTypes(old_event.dispatchType, |
| 305 event_to_coalesce.dispatchType); |
| 306 } |
| 307 |
| 308 bool CanCoalesce(const WebGestureEvent& event_to_coalesce, |
| 309 const WebGestureEvent& event) { |
| 310 if (event.type != event_to_coalesce.type || |
| 311 event.sourceDevice != event_to_coalesce.sourceDevice || |
| 312 event.modifiers != event_to_coalesce.modifiers) |
| 313 return false; |
| 314 |
| 315 if (event.type == WebInputEvent::GestureScrollUpdate) |
| 316 return true; |
| 317 |
| 318 // GesturePinchUpdate scales can be combined only if they share a focal point, |
| 319 // e.g., with double-tap drag zoom. |
| 320 if (event.type == WebInputEvent::GesturePinchUpdate && |
| 321 event.x == event_to_coalesce.x && event.y == event_to_coalesce.y) |
| 322 return true; |
| 323 |
| 324 return false; |
| 325 } |
| 326 |
| 327 void Coalesce(const WebGestureEvent& event_to_coalesce, |
| 328 WebGestureEvent* event) { |
| 329 DCHECK(CanCoalesce(event_to_coalesce, *event)); |
| 330 if (event->type == WebInputEvent::GestureScrollUpdate) { |
| 331 event->data.scrollUpdate.deltaX += |
| 332 event_to_coalesce.data.scrollUpdate.deltaX; |
| 333 event->data.scrollUpdate.deltaY += |
| 334 event_to_coalesce.data.scrollUpdate.deltaY; |
| 335 DCHECK_EQ( |
| 336 event->data.scrollUpdate.previousUpdateInSequencePrevented, |
| 337 event_to_coalesce.data.scrollUpdate.previousUpdateInSequencePrevented); |
| 338 } else if (event->type == WebInputEvent::GesturePinchUpdate) { |
| 339 event->data.pinchUpdate.scale *= event_to_coalesce.data.pinchUpdate.scale; |
| 340 // Ensure the scale remains bounded above 0 and below Infinity so that |
| 341 // we can reliably perform operations like log on the values. |
| 342 if (event->data.pinchUpdate.scale < numeric_limits<float>::min()) |
| 343 event->data.pinchUpdate.scale = numeric_limits<float>::min(); |
| 344 else if (event->data.pinchUpdate.scale > numeric_limits<float>::max()) |
| 345 event->data.pinchUpdate.scale = numeric_limits<float>::max(); |
| 346 } |
| 347 } |
| 348 |
| 163 } // namespace | 349 } // namespace |
| 164 | 350 |
| 351 bool CanCoalesce(const blink::WebInputEvent& event_to_coalesce, |
| 352 const blink::WebInputEvent& event) { |
| 353 if (blink::WebInputEvent::isGestureEventType(event_to_coalesce.type) && |
| 354 blink::WebInputEvent::isGestureEventType(event.type)) { |
| 355 return CanCoalesce( |
| 356 static_cast<const blink::WebGestureEvent&>(event_to_coalesce), |
| 357 static_cast<const blink::WebGestureEvent&>(event)); |
| 358 } |
| 359 if (blink::WebInputEvent::isMouseEventType(event_to_coalesce.type) && |
| 360 blink::WebInputEvent::isMouseEventType(event.type)) { |
| 361 return CanCoalesce( |
| 362 static_cast<const blink::WebMouseEvent&>(event_to_coalesce), |
| 363 static_cast<const blink::WebMouseEvent&>(event)); |
| 364 } |
| 365 if (blink::WebInputEvent::isTouchEventType(event_to_coalesce.type) && |
| 366 blink::WebInputEvent::isTouchEventType(event.type)) { |
| 367 return CanCoalesce( |
| 368 static_cast<const blink::WebTouchEvent&>(event_to_coalesce), |
| 369 static_cast<const blink::WebTouchEvent&>(event)); |
| 370 } |
| 371 if (event_to_coalesce.type == blink::WebInputEvent::MouseWheel && |
| 372 event.type == blink::WebInputEvent::MouseWheel) { |
| 373 return CanCoalesce( |
| 374 static_cast<const blink::WebMouseWheelEvent&>(event_to_coalesce), |
| 375 static_cast<const blink::WebMouseWheelEvent&>(event)); |
| 376 } |
| 377 return false; |
| 378 } |
| 379 |
| 380 void Coalesce(const blink::WebInputEvent& event_to_coalesce, |
| 381 blink::WebInputEvent* event) { |
| 382 if (blink::WebInputEvent::isGestureEventType(event_to_coalesce.type) && |
| 383 blink::WebInputEvent::isGestureEventType(event->type)) { |
| 384 Coalesce(static_cast<const blink::WebGestureEvent&>(event_to_coalesce), |
| 385 static_cast<blink::WebGestureEvent*>(event)); |
| 386 return; |
| 387 } |
| 388 if (blink::WebInputEvent::isMouseEventType(event_to_coalesce.type) && |
| 389 blink::WebInputEvent::isMouseEventType(event->type)) { |
| 390 Coalesce(static_cast<const blink::WebMouseEvent&>(event_to_coalesce), |
| 391 static_cast<blink::WebMouseEvent*>(event)); |
| 392 return; |
| 393 } |
| 394 if (blink::WebInputEvent::isTouchEventType(event_to_coalesce.type) && |
| 395 blink::WebInputEvent::isTouchEventType(event->type)) { |
| 396 Coalesce(static_cast<const blink::WebTouchEvent&>(event_to_coalesce), |
| 397 static_cast<blink::WebTouchEvent*>(event)); |
| 398 return; |
| 399 } |
| 400 if (event_to_coalesce.type == blink::WebInputEvent::MouseWheel && |
| 401 event->type == blink::WebInputEvent::MouseWheel) { |
| 402 Coalesce(static_cast<const blink::WebMouseWheelEvent&>(event_to_coalesce), |
| 403 static_cast<blink::WebMouseWheelEvent*>(event)); |
| 404 } |
| 405 } |
| 406 |
| 165 blink::WebTouchEvent CreateWebTouchEventFromMotionEvent( | 407 blink::WebTouchEvent CreateWebTouchEventFromMotionEvent( |
| 166 const MotionEvent& event, | 408 const MotionEvent& event, |
| 167 bool moved_beyond_slop_region) { | 409 bool moved_beyond_slop_region) { |
| 168 static_assert(static_cast<int>(MotionEvent::MAX_TOUCH_POINT_COUNT) == | 410 static_assert(static_cast<int>(MotionEvent::MAX_TOUCH_POINT_COUNT) == |
| 169 static_cast<int>(blink::WebTouchEvent::kTouchesLengthCap), | 411 static_cast<int>(blink::WebTouchEvent::kTouchesLengthCap), |
| 170 "inconsistent maximum number of active touch points"); | 412 "inconsistent maximum number of active touch points"); |
| 171 | 413 |
| 172 blink::WebTouchEvent result; | 414 blink::WebTouchEvent result; |
| 173 | 415 |
| 174 result.type = ToWebInputEventType(event.GetAction()); | 416 result.type = ToWebInputEventType(event.GetAction()); |
| (...skipping 359 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 534 case DomKeyLocation::RIGHT: | 776 case DomKeyLocation::RIGHT: |
| 535 return blink::WebInputEvent::IsRight; | 777 return blink::WebInputEvent::IsRight; |
| 536 case DomKeyLocation::NUMPAD: | 778 case DomKeyLocation::NUMPAD: |
| 537 return blink::WebInputEvent::IsKeyPad; | 779 return blink::WebInputEvent::IsKeyPad; |
| 538 case DomKeyLocation::STANDARD: | 780 case DomKeyLocation::STANDARD: |
| 539 break; | 781 break; |
| 540 } | 782 } |
| 541 return static_cast<blink::WebInputEvent::Modifiers>(0); | 783 return static_cast<blink::WebInputEvent::Modifiers>(0); |
| 542 } | 784 } |
| 543 | 785 |
| 786 bool IsGestureScollOrPinch(WebInputEvent::Type type) { |
| 787 switch (type) { |
| 788 case blink::WebGestureEvent::GestureScrollBegin: |
| 789 case blink::WebGestureEvent::GestureScrollUpdate: |
| 790 case blink::WebGestureEvent::GestureScrollEnd: |
| 791 case blink::WebGestureEvent::GesturePinchBegin: |
| 792 case blink::WebGestureEvent::GesturePinchUpdate: |
| 793 case blink::WebGestureEvent::GesturePinchEnd: |
| 794 return true; |
| 795 default: |
| 796 return false; |
| 797 } |
| 798 } |
| 799 |
| 800 bool IsContinuousGestureEvent(WebInputEvent::Type type) { |
| 801 switch (type) { |
| 802 case blink::WebGestureEvent::GestureScrollUpdate: |
| 803 case blink::WebGestureEvent::GesturePinchUpdate: |
| 804 return true; |
| 805 default: |
| 806 return false; |
| 807 } |
| 808 } |
| 809 |
| 544 } // namespace ui | 810 } // namespace ui |
| OLD | NEW |