| 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 ToWebTouchEventType(MotionEvent::Action action) { | 43 WebInputEvent::Type ToWebTouchEventType(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 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 187 touch.rotationAngle = orientation_deg; | 194 touch.rotationAngle = orientation_deg; |
| 188 } else { | 195 } else { |
| 189 touch.radiusX = major_radius; | 196 touch.radiusX = major_radius; |
| 190 touch.radiusY = minor_radius; | 197 touch.radiusY = minor_radius; |
| 191 touch.rotationAngle = orientation_deg + 90; | 198 touch.rotationAngle = orientation_deg + 90; |
| 192 } | 199 } |
| 193 | 200 |
| 194 return touch; | 201 return touch; |
| 195 } | 202 } |
| 196 | 203 |
| 204 float GetUnacceleratedDelta(float accelerated_delta, float acceleration_ratio) { |
| 205 return accelerated_delta * acceleration_ratio; |
| 206 } |
| 207 |
| 208 float GetAccelerationRatio(float accelerated_delta, float unaccelerated_delta) { |
| 209 if (unaccelerated_delta == 0.f || accelerated_delta == 0.f) |
| 210 return 1.f; |
| 211 return unaccelerated_delta / accelerated_delta; |
| 212 } |
| 213 |
| 214 // Returns |kInvalidTouchIndex| iff |event| lacks a touch with an ID of |id|. |
| 215 int GetIndexOfTouchID(const WebTouchEvent& event, int id) { |
| 216 for (unsigned i = 0; i < event.touchesLength; ++i) { |
| 217 if (event.touches[i].id == id) |
| 218 return i; |
| 219 } |
| 220 return kInvalidTouchIndex; |
| 221 } |
| 222 |
| 223 WebInputEvent::DispatchType MergeDispatchTypes( |
| 224 WebInputEvent::DispatchType type_1, |
| 225 WebInputEvent::DispatchType type_2) { |
| 226 static_assert(WebInputEvent::DispatchType::Blocking < |
| 227 WebInputEvent::DispatchType::EventNonBlocking, |
| 228 "Enum not ordered correctly"); |
| 229 static_assert(WebInputEvent::DispatchType::EventNonBlocking < |
| 230 WebInputEvent::DispatchType::ListenersNonBlockingPassive, |
| 231 "Enum not ordered correctly"); |
| 232 static_assert( |
| 233 WebInputEvent::DispatchType::ListenersNonBlockingPassive < |
| 234 WebInputEvent::DispatchType::ListenersForcedNonBlockingDueToFling, |
| 235 "Enum not ordered correctly"); |
| 236 return static_cast<WebInputEvent::DispatchType>( |
| 237 std::min(static_cast<int>(type_1), static_cast<int>(type_2))); |
| 238 } |
| 239 |
| 240 bool CanCoalesce(const WebMouseEvent& event_to_coalesce, |
| 241 const WebMouseEvent& event) { |
| 242 return event.type == event_to_coalesce.type && |
| 243 event.type == WebInputEvent::MouseMove; |
| 244 } |
| 245 |
| 246 void Coalesce(const WebMouseEvent& event_to_coalesce, WebMouseEvent* event) { |
| 247 DCHECK(CanCoalesce(event_to_coalesce, *event)); |
| 248 // Accumulate movement deltas. |
| 249 int x = event->movementX; |
| 250 int y = event->movementY; |
| 251 *event = event_to_coalesce; |
| 252 event->movementX += x; |
| 253 event->movementY += y; |
| 254 } |
| 255 |
| 256 bool CanCoalesce(const WebMouseWheelEvent& event_to_coalesce, |
| 257 const WebMouseWheelEvent& event) { |
| 258 return event.modifiers == event_to_coalesce.modifiers && |
| 259 event.scrollByPage == event_to_coalesce.scrollByPage && |
| 260 event.phase == event_to_coalesce.phase && |
| 261 event.momentumPhase == event_to_coalesce.momentumPhase && |
| 262 event.hasPreciseScrollingDeltas == |
| 263 event_to_coalesce.hasPreciseScrollingDeltas; |
| 264 } |
| 265 |
| 266 void Coalesce(const WebMouseWheelEvent& event_to_coalesce, |
| 267 WebMouseWheelEvent* event) { |
| 268 DCHECK(CanCoalesce(event_to_coalesce, *event)); |
| 269 float unaccelerated_x = |
| 270 GetUnacceleratedDelta(event->deltaX, event->accelerationRatioX) + |
| 271 GetUnacceleratedDelta(event_to_coalesce.deltaX, |
| 272 event_to_coalesce.accelerationRatioX); |
| 273 float unaccelerated_y = |
| 274 GetUnacceleratedDelta(event->deltaY, event->accelerationRatioY) + |
| 275 GetUnacceleratedDelta(event_to_coalesce.deltaY, |
| 276 event_to_coalesce.accelerationRatioY); |
| 277 float old_deltaX = event->deltaX; |
| 278 float old_deltaY = event->deltaY; |
| 279 float old_wheelTicksX = event->wheelTicksX; |
| 280 float old_wheelTicksY = event->wheelTicksY; |
| 281 float old_movementX = event->movementX; |
| 282 float old_movementY = event->movementY; |
| 283 *event = event_to_coalesce; |
| 284 event->deltaX += old_deltaX; |
| 285 event->deltaY += old_deltaY; |
| 286 event->wheelTicksX += old_wheelTicksX; |
| 287 event->wheelTicksY += old_wheelTicksY; |
| 288 event->movementX += old_movementX; |
| 289 event->movementY += old_movementY; |
| 290 event->accelerationRatioX = |
| 291 GetAccelerationRatio(event->deltaX, unaccelerated_x); |
| 292 event->accelerationRatioY = |
| 293 GetAccelerationRatio(event->deltaY, unaccelerated_y); |
| 294 } |
| 295 |
| 296 bool CanCoalesce(const WebTouchEvent& event_to_coalesce, |
| 297 const WebTouchEvent& event) { |
| 298 if (event.type != event_to_coalesce.type || |
| 299 event.type != WebInputEvent::TouchMove || |
| 300 event.modifiers != event_to_coalesce.modifiers || |
| 301 event.touchesLength != event_to_coalesce.touchesLength || |
| 302 event.touchesLength > WebTouchEvent::kTouchesLengthCap) |
| 303 return false; |
| 304 |
| 305 static_assert(WebTouchEvent::kTouchesLengthCap <= sizeof(int32_t) * 8U, |
| 306 "suboptimal kTouchesLengthCap size"); |
| 307 // Ensure that we have a 1-to-1 mapping of pointer ids between touches. |
| 308 std::bitset<WebTouchEvent::kTouchesLengthCap> unmatched_event_touches( |
| 309 (1 << event.touchesLength) - 1); |
| 310 for (unsigned i = 0; i < event_to_coalesce.touchesLength; ++i) { |
| 311 int event_touch_index = |
| 312 GetIndexOfTouchID(event, event_to_coalesce.touches[i].id); |
| 313 if (event_touch_index == kInvalidTouchIndex) |
| 314 return false; |
| 315 if (!unmatched_event_touches[event_touch_index]) |
| 316 return false; |
| 317 unmatched_event_touches[event_touch_index] = false; |
| 318 } |
| 319 return unmatched_event_touches.none(); |
| 320 } |
| 321 |
| 322 void Coalesce(const WebTouchEvent& event_to_coalesce, WebTouchEvent* event) { |
| 323 DCHECK(CanCoalesce(event_to_coalesce, *event)); |
| 324 // The WebTouchPoints include absolute position information. So it is |
| 325 // sufficient to simply replace the previous event with the new event-> |
| 326 // However, it is necessary to make sure that all the points have the |
| 327 // correct state, i.e. the touch-points that moved in the last event, but |
| 328 // didn't change in the current event, will have Stationary state. It is |
| 329 // necessary to change them back to Moved state. |
| 330 WebTouchEvent old_event = *event; |
| 331 *event = event_to_coalesce; |
| 332 for (unsigned i = 0; i < event->touchesLength; ++i) { |
| 333 int i_old = GetIndexOfTouchID(old_event, event->touches[i].id); |
| 334 if (old_event.touches[i_old].state == blink::WebTouchPoint::StateMoved) |
| 335 event->touches[i].state = blink::WebTouchPoint::StateMoved; |
| 336 } |
| 337 event->movedBeyondSlopRegion |= old_event.movedBeyondSlopRegion; |
| 338 event->dispatchType = MergeDispatchTypes(old_event.dispatchType, |
| 339 event_to_coalesce.dispatchType); |
| 340 } |
| 341 |
| 342 bool CanCoalesce(const WebGestureEvent& event_to_coalesce, |
| 343 const WebGestureEvent& event) { |
| 344 if (event.type != event_to_coalesce.type || |
| 345 event.sourceDevice != event_to_coalesce.sourceDevice || |
| 346 event.modifiers != event_to_coalesce.modifiers) |
| 347 return false; |
| 348 |
| 349 if (event.type == WebInputEvent::GestureScrollUpdate) |
| 350 return true; |
| 351 |
| 352 // GesturePinchUpdate scales can be combined only if they share a focal point, |
| 353 // e.g., with double-tap drag zoom. |
| 354 if (event.type == WebInputEvent::GesturePinchUpdate && |
| 355 event.x == event_to_coalesce.x && event.y == event_to_coalesce.y) |
| 356 return true; |
| 357 |
| 358 return false; |
| 359 } |
| 360 |
| 361 void Coalesce(const WebGestureEvent& event_to_coalesce, |
| 362 WebGestureEvent* event) { |
| 363 DCHECK(CanCoalesce(event_to_coalesce, *event)); |
| 364 if (event->type == WebInputEvent::GestureScrollUpdate) { |
| 365 event->data.scrollUpdate.deltaX += |
| 366 event_to_coalesce.data.scrollUpdate.deltaX; |
| 367 event->data.scrollUpdate.deltaY += |
| 368 event_to_coalesce.data.scrollUpdate.deltaY; |
| 369 DCHECK_EQ( |
| 370 event->data.scrollUpdate.previousUpdateInSequencePrevented, |
| 371 event_to_coalesce.data.scrollUpdate.previousUpdateInSequencePrevented); |
| 372 } else if (event->type == WebInputEvent::GesturePinchUpdate) { |
| 373 event->data.pinchUpdate.scale *= event_to_coalesce.data.pinchUpdate.scale; |
| 374 // Ensure the scale remains bounded above 0 and below Infinity so that |
| 375 // we can reliably perform operations like log on the values. |
| 376 if (event->data.pinchUpdate.scale < numeric_limits<float>::min()) |
| 377 event->data.pinchUpdate.scale = numeric_limits<float>::min(); |
| 378 else if (event->data.pinchUpdate.scale > numeric_limits<float>::max()) |
| 379 event->data.pinchUpdate.scale = numeric_limits<float>::max(); |
| 380 } |
| 381 } |
| 382 |
| 197 } // namespace | 383 } // namespace |
| 198 | 384 |
| 385 bool CanCoalesce(const blink::WebInputEvent& event_to_coalesce, |
| 386 const blink::WebInputEvent& event) { |
| 387 if (blink::WebInputEvent::isGestureEventType(event_to_coalesce.type) && |
| 388 blink::WebInputEvent::isGestureEventType(event.type)) { |
| 389 return CanCoalesce( |
| 390 static_cast<const blink::WebGestureEvent&>(event_to_coalesce), |
| 391 static_cast<const blink::WebGestureEvent&>(event)); |
| 392 } |
| 393 if (blink::WebInputEvent::isMouseEventType(event_to_coalesce.type) && |
| 394 blink::WebInputEvent::isMouseEventType(event.type)) { |
| 395 return CanCoalesce( |
| 396 static_cast<const blink::WebMouseEvent&>(event_to_coalesce), |
| 397 static_cast<const blink::WebMouseEvent&>(event)); |
| 398 } |
| 399 if (blink::WebInputEvent::isTouchEventType(event_to_coalesce.type) && |
| 400 blink::WebInputEvent::isTouchEventType(event.type)) { |
| 401 return CanCoalesce( |
| 402 static_cast<const blink::WebTouchEvent&>(event_to_coalesce), |
| 403 static_cast<const blink::WebTouchEvent&>(event)); |
| 404 } |
| 405 if (event_to_coalesce.type == blink::WebInputEvent::MouseWheel && |
| 406 event.type == blink::WebInputEvent::MouseWheel) { |
| 407 return CanCoalesce( |
| 408 static_cast<const blink::WebMouseWheelEvent&>(event_to_coalesce), |
| 409 static_cast<const blink::WebMouseWheelEvent&>(event)); |
| 410 } |
| 411 return false; |
| 412 } |
| 413 |
| 414 void Coalesce(const blink::WebInputEvent& event_to_coalesce, |
| 415 blink::WebInputEvent* event) { |
| 416 if (blink::WebInputEvent::isGestureEventType(event_to_coalesce.type) && |
| 417 blink::WebInputEvent::isGestureEventType(event->type)) { |
| 418 Coalesce(static_cast<const blink::WebGestureEvent&>(event_to_coalesce), |
| 419 static_cast<blink::WebGestureEvent*>(event)); |
| 420 return; |
| 421 } |
| 422 if (blink::WebInputEvent::isMouseEventType(event_to_coalesce.type) && |
| 423 blink::WebInputEvent::isMouseEventType(event->type)) { |
| 424 Coalesce(static_cast<const blink::WebMouseEvent&>(event_to_coalesce), |
| 425 static_cast<blink::WebMouseEvent*>(event)); |
| 426 return; |
| 427 } |
| 428 if (blink::WebInputEvent::isTouchEventType(event_to_coalesce.type) && |
| 429 blink::WebInputEvent::isTouchEventType(event->type)) { |
| 430 Coalesce(static_cast<const blink::WebTouchEvent&>(event_to_coalesce), |
| 431 static_cast<blink::WebTouchEvent*>(event)); |
| 432 return; |
| 433 } |
| 434 if (event_to_coalesce.type == blink::WebInputEvent::MouseWheel && |
| 435 event->type == blink::WebInputEvent::MouseWheel) { |
| 436 Coalesce(static_cast<const blink::WebMouseWheelEvent&>(event_to_coalesce), |
| 437 static_cast<blink::WebMouseWheelEvent*>(event)); |
| 438 } |
| 439 } |
| 440 |
| 199 blink::WebTouchEvent CreateWebTouchEventFromMotionEvent( | 441 blink::WebTouchEvent CreateWebTouchEventFromMotionEvent( |
| 200 const MotionEvent& event, | 442 const MotionEvent& event, |
| 201 bool moved_beyond_slop_region) { | 443 bool moved_beyond_slop_region) { |
| 202 static_assert(static_cast<int>(MotionEvent::MAX_TOUCH_POINT_COUNT) == | 444 static_assert(static_cast<int>(MotionEvent::MAX_TOUCH_POINT_COUNT) == |
| 203 static_cast<int>(blink::WebTouchEvent::kTouchesLengthCap), | 445 static_cast<int>(blink::WebTouchEvent::kTouchesLengthCap), |
| 204 "inconsistent maximum number of active touch points"); | 446 "inconsistent maximum number of active touch points"); |
| 205 | 447 |
| 206 blink::WebTouchEvent result; | 448 blink::WebTouchEvent result; |
| 207 | 449 |
| 208 result.type = ToWebTouchEventType(event.GetAction()); | 450 result.type = ToWebTouchEventType(event.GetAction()); |
| (...skipping 399 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 608 case DomKeyLocation::RIGHT: | 850 case DomKeyLocation::RIGHT: |
| 609 return blink::WebInputEvent::IsRight; | 851 return blink::WebInputEvent::IsRight; |
| 610 case DomKeyLocation::NUMPAD: | 852 case DomKeyLocation::NUMPAD: |
| 611 return blink::WebInputEvent::IsKeyPad; | 853 return blink::WebInputEvent::IsKeyPad; |
| 612 case DomKeyLocation::STANDARD: | 854 case DomKeyLocation::STANDARD: |
| 613 break; | 855 break; |
| 614 } | 856 } |
| 615 return static_cast<blink::WebInputEvent::Modifiers>(0); | 857 return static_cast<blink::WebInputEvent::Modifiers>(0); |
| 616 } | 858 } |
| 617 | 859 |
| 860 bool IsGestureScollOrPinch(WebInputEvent::Type type) { |
| 861 switch (type) { |
| 862 case blink::WebGestureEvent::GestureScrollBegin: |
| 863 case blink::WebGestureEvent::GestureScrollUpdate: |
| 864 case blink::WebGestureEvent::GestureScrollEnd: |
| 865 case blink::WebGestureEvent::GesturePinchBegin: |
| 866 case blink::WebGestureEvent::GesturePinchUpdate: |
| 867 case blink::WebGestureEvent::GesturePinchEnd: |
| 868 return true; |
| 869 default: |
| 870 return false; |
| 871 } |
| 872 } |
| 873 |
| 874 bool IsContinuousGestureEvent(WebInputEvent::Type type) { |
| 875 switch (type) { |
| 876 case blink::WebGestureEvent::GestureScrollUpdate: |
| 877 case blink::WebGestureEvent::GesturePinchUpdate: |
| 878 return true; |
| 879 default: |
| 880 return false; |
| 881 } |
| 882 } |
| 883 |
| 618 } // namespace ui | 884 } // namespace ui |
| OLD | NEW |