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