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> |
(...skipping 14 matching lines...) Expand all Loading... |
25 | 25 |
26 using blink::WebGestureEvent; | 26 using blink::WebGestureEvent; |
27 using blink::WebInputEvent; | 27 using blink::WebInputEvent; |
28 using blink::WebPointerProperties; | 28 using blink::WebPointerProperties; |
29 using blink::WebTouchEvent; | 29 using blink::WebTouchEvent; |
30 using blink::WebTouchPoint; | 30 using blink::WebTouchPoint; |
31 | 31 |
32 namespace ui { | 32 namespace ui { |
33 namespace { | 33 namespace { |
34 | 34 |
35 WebInputEvent::Type ToWebInputEventType(MotionEvent::Action action) { | 35 WebInputEvent::Type ToWebTouchEventType(MotionEvent::Action action) { |
36 switch (action) { | 36 switch (action) { |
37 case MotionEvent::ACTION_DOWN: | 37 case MotionEvent::ACTION_DOWN: |
38 return WebInputEvent::TouchStart; | 38 return WebInputEvent::TouchStart; |
39 case MotionEvent::ACTION_MOVE: | 39 case MotionEvent::ACTION_MOVE: |
40 return WebInputEvent::TouchMove; | 40 return WebInputEvent::TouchMove; |
41 case MotionEvent::ACTION_UP: | 41 case MotionEvent::ACTION_UP: |
42 return WebInputEvent::TouchEnd; | 42 return WebInputEvent::TouchEnd; |
43 case MotionEvent::ACTION_CANCEL: | 43 case MotionEvent::ACTION_CANCEL: |
44 return WebInputEvent::TouchCancel; | 44 return WebInputEvent::TouchCancel; |
45 case MotionEvent::ACTION_POINTER_DOWN: | 45 case MotionEvent::ACTION_POINTER_DOWN: |
46 return WebInputEvent::TouchStart; | 46 return WebInputEvent::TouchStart; |
47 case MotionEvent::ACTION_POINTER_UP: | 47 case MotionEvent::ACTION_POINTER_UP: |
48 return WebInputEvent::TouchEnd; | 48 return WebInputEvent::TouchEnd; |
49 case MotionEvent::ACTION_NONE: | 49 case MotionEvent::ACTION_NONE: |
50 NOTREACHED(); | 50 break; |
51 return WebInputEvent::Undefined; | |
52 } | 51 } |
53 NOTREACHED() << "Invalid MotionEvent::Action."; | 52 NOTREACHED() << "Invalid MotionEvent::Action = " << action; |
54 return WebInputEvent::Undefined; | 53 return WebInputEvent::Undefined; |
55 } | 54 } |
56 | 55 |
57 // Note that the action index is meaningful only in the context of | 56 // Note that the action index is meaningful only in the context of |
58 // |ACTION_POINTER_UP| and |ACTION_POINTER_DOWN|; other actions map directly to | 57 // |ACTION_POINTER_UP| and |ACTION_POINTER_DOWN|; other actions map directly to |
59 // WebTouchPoint::State. | 58 // WebTouchPoint::State. |
60 WebTouchPoint::State ToWebTouchPointState(const MotionEvent& event, | 59 WebTouchPoint::State ToWebTouchPointState(const MotionEvent& event, |
61 size_t pointer_index) { | 60 size_t pointer_index) { |
62 switch (event.GetAction()) { | 61 switch (event.GetAction()) { |
63 case MotionEvent::ACTION_DOWN: | 62 case MotionEvent::ACTION_DOWN: |
64 return WebTouchPoint::StatePressed; | 63 return WebTouchPoint::StatePressed; |
65 case MotionEvent::ACTION_MOVE: | 64 case MotionEvent::ACTION_MOVE: |
66 return WebTouchPoint::StateMoved; | 65 return WebTouchPoint::StateMoved; |
67 case MotionEvent::ACTION_UP: | 66 case MotionEvent::ACTION_UP: |
68 return WebTouchPoint::StateReleased; | 67 return WebTouchPoint::StateReleased; |
69 case MotionEvent::ACTION_CANCEL: | 68 case MotionEvent::ACTION_CANCEL: |
70 return WebTouchPoint::StateCancelled; | 69 return WebTouchPoint::StateCancelled; |
71 case MotionEvent::ACTION_POINTER_DOWN: | 70 case MotionEvent::ACTION_POINTER_DOWN: |
72 return static_cast<int>(pointer_index) == event.GetActionIndex() | 71 return static_cast<int>(pointer_index) == event.GetActionIndex() |
73 ? WebTouchPoint::StatePressed | 72 ? WebTouchPoint::StatePressed |
74 : WebTouchPoint::StateStationary; | 73 : WebTouchPoint::StateStationary; |
75 case MotionEvent::ACTION_POINTER_UP: | 74 case MotionEvent::ACTION_POINTER_UP: |
76 return static_cast<int>(pointer_index) == event.GetActionIndex() | 75 return static_cast<int>(pointer_index) == event.GetActionIndex() |
77 ? WebTouchPoint::StateReleased | 76 ? WebTouchPoint::StateReleased |
78 : WebTouchPoint::StateStationary; | 77 : WebTouchPoint::StateStationary; |
79 case MotionEvent::ACTION_NONE: | 78 case MotionEvent::ACTION_NONE: |
80 NOTREACHED(); | 79 break; |
81 return WebTouchPoint::StateUndefined; | |
82 } | 80 } |
83 NOTREACHED() << "Invalid MotionEvent::Action."; | 81 NOTREACHED() << "Invalid MotionEvent::Action."; |
84 return WebTouchPoint::StateUndefined; | 82 return WebTouchPoint::StateUndefined; |
85 } | 83 } |
86 | 84 |
| 85 WebPointerProperties::PointerType ToWebPointerType(int tool_type) { |
| 86 switch (static_cast<MotionEvent::ToolType>(tool_type)) { |
| 87 case MotionEvent::TOOL_TYPE_UNKNOWN: |
| 88 return WebPointerProperties::PointerType::Unknown; |
| 89 case MotionEvent::TOOL_TYPE_FINGER: |
| 90 return WebPointerProperties::PointerType::Touch; |
| 91 case MotionEvent::TOOL_TYPE_STYLUS: |
| 92 return WebPointerProperties::PointerType::Pen; |
| 93 case MotionEvent::TOOL_TYPE_MOUSE: |
| 94 return WebPointerProperties::PointerType::Mouse; |
| 95 case MotionEvent::TOOL_TYPE_ERASER: |
| 96 return WebPointerProperties::PointerType::Eraser; |
| 97 } |
| 98 NOTREACHED() << "Invalid MotionEvent::ToolType = " << tool_type; |
| 99 return WebPointerProperties::PointerType::Unknown; |
| 100 } |
| 101 |
| 102 WebPointerProperties::Button ToWebPointerButton(int android_button_state) { |
| 103 if (android_button_state & MotionEvent::BUTTON_PRIMARY) |
| 104 return WebPointerProperties::Button::Left; |
| 105 else if (android_button_state & MotionEvent::BUTTON_SECONDARY) |
| 106 return WebPointerProperties::Button::Right; |
| 107 else if (android_button_state & MotionEvent::BUTTON_TERTIARY) |
| 108 return WebPointerProperties::Button::Middle; |
| 109 else if (android_button_state & MotionEvent::BUTTON_BACK) |
| 110 return WebPointerProperties::Button::X1; |
| 111 else if (android_button_state & MotionEvent::BUTTON_FORWARD) |
| 112 return WebPointerProperties::Button::X2; |
| 113 else if (android_button_state & MotionEvent::BUTTON_STYLUS_PRIMARY) |
| 114 return WebPointerProperties::Button::Left; |
| 115 else if (android_button_state & MotionEvent::BUTTON_STYLUS_SECONDARY) |
| 116 return WebPointerProperties::Button::Right; |
| 117 else |
| 118 return WebPointerProperties::Button::NoButton; |
| 119 } |
| 120 |
87 WebTouchPoint CreateWebTouchPoint(const MotionEvent& event, | 121 WebTouchPoint CreateWebTouchPoint(const MotionEvent& event, |
88 size_t pointer_index) { | 122 size_t pointer_index) { |
89 WebTouchPoint touch; | 123 WebTouchPoint touch; |
90 touch.id = event.GetPointerId(pointer_index); | 124 |
91 touch.pointerType = ToWebPointerType(event.GetToolType(pointer_index)); | 125 SetWebPointerPropertiesFromMotionEventData( |
| 126 touch, event.GetPointerId(pointer_index), |
| 127 event.GetPressure(pointer_index), event.GetOrientation(pointer_index), |
| 128 event.GetTilt(pointer_index), 0 /* no button changed */, |
| 129 event.GetToolType(pointer_index)); |
| 130 |
92 touch.state = ToWebTouchPointState(event, pointer_index); | 131 touch.state = ToWebTouchPointState(event, pointer_index); |
93 touch.position.x = event.GetX(pointer_index); | 132 touch.position.x = event.GetX(pointer_index); |
94 touch.position.y = event.GetY(pointer_index); | 133 touch.position.y = event.GetY(pointer_index); |
95 touch.screenPosition.x = event.GetRawX(pointer_index); | 134 touch.screenPosition.x = event.GetRawX(pointer_index); |
96 touch.screenPosition.y = event.GetRawY(pointer_index); | 135 touch.screenPosition.y = event.GetRawY(pointer_index); |
97 | 136 |
98 // A note on touch ellipse specifications: | 137 // A note on touch ellipse specifications: |
99 // | 138 // |
100 // Android MotionEvent provides the major and minor axes of the touch ellipse, | 139 // Android MotionEvent provides the major and minor axes of the touch ellipse, |
101 // as well as the orientation of the major axis clockwise from vertical, in | 140 // as well as the orientation of the major axis clockwise from vertical, in |
102 // radians. See: | 141 // radians. See: |
103 // http://developer.android.com/reference/android/view/MotionEvent.html | 142 // http://developer.android.com/reference/android/view/MotionEvent.html |
104 // | 143 // |
105 // The proposed extension to W3C Touch Events specifies the touch ellipse | 144 // The proposed extension to W3C Touch Events specifies the touch ellipse |
106 // using two radii along x- & y-axes and a positive acute rotation angle in | 145 // using two radii along x- & y-axes and a positive acute rotation angle in |
107 // degrees. See: | 146 // degrees. See: |
108 // http://dvcs.w3.org/hg/webevents/raw-file/default/touchevents.html | 147 // http://dvcs.w3.org/hg/webevents/raw-file/default/touchevents.html |
109 | 148 |
110 float major_radius = event.GetTouchMajor(pointer_index) / 2.f; | 149 float major_radius = event.GetTouchMajor(pointer_index) / 2.f; |
111 float minor_radius = event.GetTouchMinor(pointer_index) / 2.f; | 150 float minor_radius = event.GetTouchMinor(pointer_index) / 2.f; |
| 151 float orientation_deg = event.GetOrientation(pointer_index) * 180.f / M_PI; |
112 | 152 |
113 float orientation_rad = event.GetOrientation(pointer_index); | |
114 float orientation_deg = orientation_rad * 180.f / M_PI; | |
115 DCHECK_GE(major_radius, 0); | 153 DCHECK_GE(major_radius, 0); |
116 DCHECK_GE(minor_radius, 0); | 154 DCHECK_GE(minor_radius, 0); |
117 DCHECK_GE(major_radius, minor_radius); | 155 DCHECK_GE(major_radius, minor_radius); |
118 // Orientation lies in [-180, 180] for a stylus, and [-90, 90] for other | 156 // Orientation lies in [-180, 180] for a stylus, and [-90, 90] for other |
119 // touchscreen inputs. There are exceptions on Android when a device is | 157 // touchscreen inputs. There are exceptions on Android when a device is |
120 // rotated, yielding touch orientations in the range of [-180, 180]. | 158 // rotated, yielding touch orientations in the range of [-180, 180]. |
121 // Regardless, normalise to [-90, 90), allowing a small tolerance to account | 159 // Regardless, normalise to [-90, 90), allowing a small tolerance to account |
122 // for floating point conversion. | 160 // for floating point conversion. |
123 // TODO(e_hakkinen): Also pass unaltered stylus orientation, avoiding loss of | 161 // TODO(e_hakkinen): Also pass unaltered stylus orientation, avoiding loss of |
124 // quadrant information, see crbug.com/493728. | 162 // quadrant information, see crbug.com/493728. |
(...skipping 10 matching lines...) Expand all Loading... |
135 // report elliptical touches). | 173 // report elliptical touches). |
136 touch.radiusX = minor_radius; | 174 touch.radiusX = minor_radius; |
137 touch.radiusY = major_radius; | 175 touch.radiusY = major_radius; |
138 touch.rotationAngle = orientation_deg; | 176 touch.rotationAngle = orientation_deg; |
139 } else { | 177 } else { |
140 touch.radiusX = major_radius; | 178 touch.radiusX = major_radius; |
141 touch.radiusY = minor_radius; | 179 touch.radiusY = minor_radius; |
142 touch.rotationAngle = orientation_deg + 90; | 180 touch.rotationAngle = orientation_deg + 90; |
143 } | 181 } |
144 | 182 |
145 touch.force = event.GetPressure(pointer_index); | |
146 | |
147 if (event.GetToolType(pointer_index) == MotionEvent::TOOL_TYPE_STYLUS) { | |
148 // A stylus points to a direction specified by orientation and tilts to | |
149 // the opposite direction. Coordinate system is left-handed. | |
150 float tilt_rad = event.GetTilt(pointer_index); | |
151 float r = sin(tilt_rad); | |
152 float z = cos(tilt_rad); | |
153 touch.tiltX = lround(atan2(sin(-orientation_rad) * r, z) * 180.f / M_PI); | |
154 touch.tiltY = lround(atan2(cos(-orientation_rad) * r, z) * 180.f / M_PI); | |
155 } else { | |
156 touch.tiltX = touch.tiltY = 0; | |
157 } | |
158 | |
159 return touch; | 183 return touch; |
160 } | 184 } |
161 | 185 |
162 } // namespace | 186 } // namespace |
163 | 187 |
164 blink::WebTouchEvent CreateWebTouchEventFromMotionEvent( | 188 blink::WebTouchEvent CreateWebTouchEventFromMotionEvent( |
165 const MotionEvent& event, | 189 const MotionEvent& event, |
166 bool moved_beyond_slop_region) { | 190 bool moved_beyond_slop_region) { |
167 static_assert(static_cast<int>(MotionEvent::MAX_TOUCH_POINT_COUNT) == | 191 static_assert(static_cast<int>(MotionEvent::MAX_TOUCH_POINT_COUNT) == |
168 static_cast<int>(blink::WebTouchEvent::kTouchesLengthCap), | 192 static_cast<int>(blink::WebTouchEvent::kTouchesLengthCap), |
169 "inconsistent maximum number of active touch points"); | 193 "inconsistent maximum number of active touch points"); |
170 | 194 |
171 blink::WebTouchEvent result; | 195 blink::WebTouchEvent result; |
172 | 196 |
173 result.type = ToWebInputEventType(event.GetAction()); | 197 result.type = ToWebTouchEventType(event.GetAction()); |
174 result.dispatchType = result.type == WebInputEvent::TouchCancel | 198 result.dispatchType = result.type == WebInputEvent::TouchCancel |
175 ? WebInputEvent::EventNonBlocking | 199 ? WebInputEvent::EventNonBlocking |
176 : WebInputEvent::Blocking; | 200 : WebInputEvent::Blocking; |
177 result.timeStampSeconds = ui::EventTimeStampToSeconds(event.GetEventTime()); | 201 result.timeStampSeconds = ui::EventTimeStampToSeconds(event.GetEventTime()); |
178 result.movedBeyondSlopRegion = moved_beyond_slop_region; | 202 result.movedBeyondSlopRegion = moved_beyond_slop_region; |
| 203 |
179 result.modifiers = EventFlagsToWebEventModifiers(event.GetFlags()); | 204 result.modifiers = EventFlagsToWebEventModifiers(event.GetFlags()); |
| 205 // TODO(mustaq): MotionEvent flags seems unrelated, should use |
| 206 // metaState instead? |
| 207 |
180 DCHECK_NE(event.GetUniqueEventId(), 0U); | 208 DCHECK_NE(event.GetUniqueEventId(), 0U); |
181 result.uniqueTouchEventId = event.GetUniqueEventId(); | 209 result.uniqueTouchEventId = event.GetUniqueEventId(); |
182 result.touchesLength = | 210 result.touchesLength = |
183 std::min(static_cast<unsigned>(event.GetPointerCount()), | 211 std::min(static_cast<unsigned>(event.GetPointerCount()), |
184 static_cast<unsigned>(WebTouchEvent::kTouchesLengthCap)); | 212 static_cast<unsigned>(WebTouchEvent::kTouchesLengthCap)); |
185 DCHECK_GT(result.touchesLength, 0U); | 213 DCHECK_GT(result.touchesLength, 0U); |
186 | 214 |
187 for (size_t i = 0; i < result.touchesLength; ++i) | 215 for (size_t i = 0; i < result.touchesLength; ++i) |
188 result.touches[i] = CreateWebTouchPoint(event, i); | 216 result.touches[i] = CreateWebTouchPoint(event, i); |
189 | 217 |
(...skipping 266 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
456 break; | 484 break; |
457 | 485 |
458 // TODO(oshima): Find out if ContextMenu needs to be scaled. | 486 // TODO(oshima): Find out if ContextMenu needs to be scaled. |
459 default: | 487 default: |
460 break; | 488 break; |
461 } | 489 } |
462 } | 490 } |
463 return scaled_event; | 491 return scaled_event; |
464 } | 492 } |
465 | 493 |
466 WebPointerProperties::PointerType ToWebPointerType( | 494 WebInputEvent::Type ToWebMouseEventType(MotionEvent::Action action) { |
467 MotionEvent::ToolType tool_type) { | 495 switch (action) { |
468 switch (tool_type) { | 496 case MotionEvent::ACTION_DOWN: |
469 case MotionEvent::TOOL_TYPE_UNKNOWN: | 497 return WebInputEvent::MouseDown; |
470 return WebPointerProperties::PointerType::Unknown; | 498 case MotionEvent::ACTION_MOVE: |
471 case MotionEvent::TOOL_TYPE_FINGER: | 499 return WebInputEvent::MouseMove; |
472 return WebPointerProperties::PointerType::Touch; | 500 case MotionEvent::ACTION_UP: |
473 case MotionEvent::TOOL_TYPE_STYLUS: | 501 return WebInputEvent::MouseUp; |
474 return WebPointerProperties::PointerType::Pen; | 502 case MotionEvent::ACTION_NONE: |
475 case MotionEvent::TOOL_TYPE_MOUSE: | 503 case MotionEvent::ACTION_CANCEL: |
476 return WebPointerProperties::PointerType::Mouse; | 504 case MotionEvent::ACTION_POINTER_DOWN: |
477 case MotionEvent::TOOL_TYPE_ERASER: | 505 case MotionEvent::ACTION_POINTER_UP: |
478 return WebPointerProperties::PointerType::Eraser; | 506 break; |
479 } | 507 } |
480 NOTREACHED() << "Invalid MotionEvent::ToolType = " << tool_type; | 508 NOTREACHED() << "Invalid MotionEvent::Action = " << action; |
481 return WebPointerProperties::PointerType::Unknown; | 509 return WebInputEvent::Undefined; |
| 510 } |
| 511 |
| 512 void SetWebPointerPropertiesFromMotionEventData( |
| 513 WebPointerProperties& webPointerProperties, |
| 514 int pointer_id, |
| 515 float pressure, |
| 516 float orientation_rad, |
| 517 float tilt_rad, |
| 518 int android_buttons_changed, |
| 519 int tool_type) { |
| 520 |
| 521 webPointerProperties.id = pointer_id; |
| 522 webPointerProperties.force = pressure; |
| 523 |
| 524 if (tool_type == MotionEvent::TOOL_TYPE_STYLUS) { |
| 525 // A stylus points to a direction specified by orientation and tilts to |
| 526 // the opposite direction. Coordinate system is left-handed. |
| 527 float r = sin(tilt_rad); |
| 528 float z = cos(tilt_rad); |
| 529 webPointerProperties.tiltX = |
| 530 lround(atan2(sin(-orientation_rad) * r, z) * 180.f / M_PI); |
| 531 webPointerProperties.tiltY = |
| 532 lround(atan2(cos(-orientation_rad) * r, z) * 180.f / M_PI); |
| 533 } else { |
| 534 webPointerProperties.tiltX = webPointerProperties.tiltY = 0; |
| 535 } |
| 536 |
| 537 webPointerProperties.button = ToWebPointerButton(android_buttons_changed); |
| 538 webPointerProperties.pointerType = ToWebPointerType(tool_type); |
482 } | 539 } |
483 | 540 |
484 int WebEventModifiersToEventFlags(int modifiers) { | 541 int WebEventModifiersToEventFlags(int modifiers) { |
485 int flags = 0; | 542 int flags = 0; |
486 | 543 |
487 if (modifiers & blink::WebInputEvent::ShiftKey) | 544 if (modifiers & blink::WebInputEvent::ShiftKey) |
488 flags |= EF_SHIFT_DOWN; | 545 flags |= EF_SHIFT_DOWN; |
489 if (modifiers & blink::WebInputEvent::ControlKey) | 546 if (modifiers & blink::WebInputEvent::ControlKey) |
490 flags |= EF_CONTROL_DOWN; | 547 flags |= EF_CONTROL_DOWN; |
491 if (modifiers & blink::WebInputEvent::AltKey) | 548 if (modifiers & blink::WebInputEvent::AltKey) |
(...skipping 26 matching lines...) Expand all Loading... |
518 return blink::WebInputEvent::IsRight; | 575 return blink::WebInputEvent::IsRight; |
519 case DomKeyLocation::NUMPAD: | 576 case DomKeyLocation::NUMPAD: |
520 return blink::WebInputEvent::IsKeyPad; | 577 return blink::WebInputEvent::IsKeyPad; |
521 case DomKeyLocation::STANDARD: | 578 case DomKeyLocation::STANDARD: |
522 break; | 579 break; |
523 } | 580 } |
524 return static_cast<blink::WebInputEvent::Modifiers>(0); | 581 return static_cast<blink::WebInputEvent::Modifiers>(0); |
525 } | 582 } |
526 | 583 |
527 } // namespace ui | 584 } // namespace ui |
OLD | NEW |