cygprofile: increase timeouts to allow showing web contents
[chromium-blink-merge.git] / ui / events / blink / blink_event_util.cc
blobe985243a863f3d21ed1bf8b2b3808bca6c49a684
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
3 // found in the LICENSE file.
5 // MSVC++ requires this to be set before any other includes to get M_PI.
6 #define _USE_MATH_DEFINES
8 #include "ui/events/blink/blink_event_util.h"
10 #include <cmath>
12 #include "base/time/time.h"
13 #include "third_party/WebKit/public/web/WebInputEvent.h"
14 #include "ui/events/event_constants.h"
15 #include "ui/events/gesture_detection/gesture_event_data.h"
16 #include "ui/events/gesture_detection/motion_event.h"
17 #include "ui/events/gesture_event_details.h"
18 #include "ui/gfx/geometry/safe_integer_conversions.h"
20 using blink::WebGestureEvent;
21 using blink::WebInputEvent;
22 using blink::WebTouchEvent;
23 using blink::WebTouchPoint;
25 namespace ui {
26 namespace {
28 WebInputEvent::Type ToWebInputEventType(MotionEvent::Action action) {
29 switch (action) {
30 case MotionEvent::ACTION_DOWN:
31 return WebInputEvent::TouchStart;
32 case MotionEvent::ACTION_MOVE:
33 return WebInputEvent::TouchMove;
34 case MotionEvent::ACTION_UP:
35 return WebInputEvent::TouchEnd;
36 case MotionEvent::ACTION_CANCEL:
37 return WebInputEvent::TouchCancel;
38 case MotionEvent::ACTION_POINTER_DOWN:
39 return WebInputEvent::TouchStart;
40 case MotionEvent::ACTION_POINTER_UP:
41 return WebInputEvent::TouchEnd;
42 case MotionEvent::ACTION_NONE:
43 NOTREACHED();
44 return WebInputEvent::Undefined;
46 NOTREACHED() << "Invalid MotionEvent::Action.";
47 return WebInputEvent::Undefined;
50 // Note that the action index is meaningful only in the context of
51 // |ACTION_POINTER_UP| and |ACTION_POINTER_DOWN|; other actions map directly to
52 // WebTouchPoint::State.
53 WebTouchPoint::State ToWebTouchPointState(const MotionEvent& event,
54 size_t pointer_index) {
55 switch (event.GetAction()) {
56 case MotionEvent::ACTION_DOWN:
57 return WebTouchPoint::StatePressed;
58 case MotionEvent::ACTION_MOVE:
59 return WebTouchPoint::StateMoved;
60 case MotionEvent::ACTION_UP:
61 return WebTouchPoint::StateReleased;
62 case MotionEvent::ACTION_CANCEL:
63 return WebTouchPoint::StateCancelled;
64 case MotionEvent::ACTION_POINTER_DOWN:
65 return static_cast<int>(pointer_index) == event.GetActionIndex()
66 ? WebTouchPoint::StatePressed
67 : WebTouchPoint::StateStationary;
68 case MotionEvent::ACTION_POINTER_UP:
69 return static_cast<int>(pointer_index) == event.GetActionIndex()
70 ? WebTouchPoint::StateReleased
71 : WebTouchPoint::StateStationary;
72 case MotionEvent::ACTION_NONE:
73 NOTREACHED();
74 return WebTouchPoint::StateUndefined;
76 NOTREACHED() << "Invalid MotionEvent::Action.";
77 return WebTouchPoint::StateUndefined;
80 WebTouchPoint::PointerType ToWebTouchPointPointerType(const MotionEvent& event,
81 size_t pointer_index) {
82 switch (event.GetToolType(pointer_index)) {
83 case MotionEvent::TOOL_TYPE_UNKNOWN:
84 return WebTouchPoint::PointerTypeUnknown;
85 case MotionEvent::TOOL_TYPE_FINGER:
86 return WebTouchPoint::PointerTypeTouch;
87 case MotionEvent::TOOL_TYPE_STYLUS:
88 return WebTouchPoint::PointerTypePen;
89 case MotionEvent::TOOL_TYPE_MOUSE:
90 return WebTouchPoint::PointerTypeMouse;
91 case MotionEvent::TOOL_TYPE_ERASER:
92 return WebTouchPoint::PointerTypeUnknown;
94 NOTREACHED() << "Invalid MotionEvent::ToolType = "
95 << event.GetToolType(pointer_index);
96 return WebTouchPoint::PointerTypeUnknown;
99 WebTouchPoint CreateWebTouchPoint(const MotionEvent& event,
100 size_t pointer_index) {
101 WebTouchPoint touch;
102 touch.id = event.GetPointerId(pointer_index);
103 touch.pointerType = ToWebTouchPointPointerType(event, pointer_index);
104 touch.state = ToWebTouchPointState(event, pointer_index);
105 touch.position.x = event.GetX(pointer_index);
106 touch.position.y = event.GetY(pointer_index);
107 touch.screenPosition.x = event.GetRawX(pointer_index);
108 touch.screenPosition.y = event.GetRawY(pointer_index);
110 // A note on touch ellipse specifications:
112 // Android MotionEvent provides the major and minor axes of the touch ellipse,
113 // as well as the orientation of the major axis clockwise from vertical, in
114 // radians. See:
115 // http://developer.android.com/reference/android/view/MotionEvent.html
117 // The proposed extension to W3C Touch Events specifies the touch ellipse
118 // using two radii along x- & y-axes and a positive acute rotation angle in
119 // degrees. See:
120 // http://dvcs.w3.org/hg/webevents/raw-file/default/touchevents.html
122 float major_radius = event.GetTouchMajor(pointer_index) / 2.f;
123 float minor_radius = event.GetTouchMinor(pointer_index) / 2.f;
125 DCHECK_LE(minor_radius, major_radius);
126 DCHECK_IMPLIES(major_radius, minor_radius);
128 float orientation_deg = event.GetOrientation(pointer_index) * 180.f / M_PI;
129 DCHECK_GE(major_radius, 0);
130 DCHECK_GE(minor_radius, 0);
131 DCHECK_GE(major_radius, minor_radius);
132 if (event.GetToolType(pointer_index) == MotionEvent::TOOL_TYPE_STYLUS) {
133 // Orientation lies in [-180, 180] for a stylus. Normalise to [-90, 90).
134 // Allow a small bound tolerance to account for floating point conversion.
135 // TODO(e_hakkinen): crbug.com/493728: Pass also unaltered orientation
136 // to touch in order not to lose quadrant information.
137 DCHECK_GT(orientation_deg, -180.01f);
138 DCHECK_LT(orientation_deg, 180.01f);
139 if (orientation_deg >= 90.f)
140 orientation_deg -= 180.f;
141 else if (orientation_deg < -90.f)
142 orientation_deg += 180.f;
143 } else {
144 // Orientation lies in [-90, 90] for a touch. Normalise to [-90, 90).
145 // Allow a small bound tolerance to account for floating point conversion.
146 DCHECK_GT(orientation_deg, -90.01f);
147 DCHECK_LT(orientation_deg, 90.01f);
148 if (orientation_deg >= 90.f)
149 orientation_deg -= 180.f;
151 if (orientation_deg >= 0) {
152 // The case orientation_deg == 0 is handled here on purpose: although the
153 // 'else' block is equivalent in this case, we want to pass the 0 value
154 // unchanged (and 0 is the default value for many devices that don't
155 // report elliptical touches).
156 touch.radiusX = minor_radius;
157 touch.radiusY = major_radius;
158 touch.rotationAngle = orientation_deg;
159 } else {
160 touch.radiusX = major_radius;
161 touch.radiusY = minor_radius;
162 touch.rotationAngle = orientation_deg + 90;
165 touch.force = event.GetPressure(pointer_index);
167 return touch;
170 } // namespace
172 blink::WebTouchEvent CreateWebTouchEventFromMotionEvent(
173 const MotionEvent& event,
174 bool may_cause_scrolling) {
175 static_assert(static_cast<int>(MotionEvent::MAX_TOUCH_POINT_COUNT) ==
176 static_cast<int>(blink::WebTouchEvent::touchesLengthCap),
177 "inconsistent maximum number of active touch points");
179 blink::WebTouchEvent result;
181 result.type = ToWebInputEventType(event.GetAction());
182 result.cancelable = (result.type != WebInputEvent::TouchCancel);
183 result.timeStampSeconds =
184 (event.GetEventTime() - base::TimeTicks()).InSecondsF(),
185 result.causesScrollingIfUncanceled = may_cause_scrolling;
186 result.modifiers = EventFlagsToWebEventModifiers(event.GetFlags());
187 DCHECK_NE(event.GetUniqueEventId(), 0U);
188 result.uniqueTouchEventId = event.GetUniqueEventId();
189 result.touchesLength =
190 std::min(static_cast<unsigned>(event.GetPointerCount()),
191 static_cast<unsigned>(WebTouchEvent::touchesLengthCap));
192 DCHECK_GT(result.touchesLength, 0U);
194 for (size_t i = 0; i < result.touchesLength; ++i)
195 result.touches[i] = CreateWebTouchPoint(event, i);
197 return result;
200 int EventFlagsToWebEventModifiers(int flags) {
201 int modifiers = 0;
203 if (flags & EF_SHIFT_DOWN)
204 modifiers |= blink::WebInputEvent::ShiftKey;
205 if (flags & EF_CONTROL_DOWN)
206 modifiers |= blink::WebInputEvent::ControlKey;
207 if (flags & EF_ALT_DOWN)
208 modifiers |= blink::WebInputEvent::AltKey;
209 if (flags & EF_COMMAND_DOWN)
210 modifiers |= blink::WebInputEvent::MetaKey;
212 if (flags & EF_LEFT_MOUSE_BUTTON)
213 modifiers |= blink::WebInputEvent::LeftButtonDown;
214 if (flags & EF_MIDDLE_MOUSE_BUTTON)
215 modifiers |= blink::WebInputEvent::MiddleButtonDown;
216 if (flags & EF_RIGHT_MOUSE_BUTTON)
217 modifiers |= blink::WebInputEvent::RightButtonDown;
218 if (flags & EF_CAPS_LOCK_DOWN)
219 modifiers |= blink::WebInputEvent::CapsLockOn;
220 if (flags & EF_IS_REPEAT)
221 modifiers |= blink::WebInputEvent::IsAutoRepeat;
223 return modifiers;
226 WebGestureEvent CreateWebGestureEvent(const GestureEventDetails& details,
227 base::TimeDelta timestamp,
228 const gfx::PointF& location,
229 const gfx::PointF& raw_location,
230 int flags) {
231 WebGestureEvent gesture;
232 gesture.timeStampSeconds = timestamp.InSecondsF();
233 gesture.x = gfx::ToFlooredInt(location.x());
234 gesture.y = gfx::ToFlooredInt(location.y());
235 gesture.globalX = gfx::ToFlooredInt(raw_location.x());
236 gesture.globalY = gfx::ToFlooredInt(raw_location.y());
237 gesture.modifiers = EventFlagsToWebEventModifiers(flags);
238 gesture.sourceDevice = blink::WebGestureDeviceTouchscreen;
240 switch (details.type()) {
241 case ET_GESTURE_SHOW_PRESS:
242 gesture.type = WebInputEvent::GestureShowPress;
243 gesture.data.showPress.width = details.bounding_box_f().width();
244 gesture.data.showPress.height = details.bounding_box_f().height();
245 break;
246 case ET_GESTURE_DOUBLE_TAP:
247 gesture.type = WebInputEvent::GestureDoubleTap;
248 DCHECK_EQ(1, details.tap_count());
249 gesture.data.tap.tapCount = details.tap_count();
250 gesture.data.tap.width = details.bounding_box_f().width();
251 gesture.data.tap.height = details.bounding_box_f().height();
252 break;
253 case ET_GESTURE_TAP:
254 gesture.type = WebInputEvent::GestureTap;
255 DCHECK_GE(details.tap_count(), 1);
256 gesture.data.tap.tapCount = details.tap_count();
257 gesture.data.tap.width = details.bounding_box_f().width();
258 gesture.data.tap.height = details.bounding_box_f().height();
259 break;
260 case ET_GESTURE_TAP_UNCONFIRMED:
261 gesture.type = WebInputEvent::GestureTapUnconfirmed;
262 DCHECK_EQ(1, details.tap_count());
263 gesture.data.tap.tapCount = details.tap_count();
264 gesture.data.tap.width = details.bounding_box_f().width();
265 gesture.data.tap.height = details.bounding_box_f().height();
266 break;
267 case ET_GESTURE_LONG_PRESS:
268 gesture.type = WebInputEvent::GestureLongPress;
269 gesture.data.longPress.width = details.bounding_box_f().width();
270 gesture.data.longPress.height = details.bounding_box_f().height();
271 break;
272 case ET_GESTURE_LONG_TAP:
273 gesture.type = WebInputEvent::GestureLongTap;
274 gesture.data.longPress.width = details.bounding_box_f().width();
275 gesture.data.longPress.height = details.bounding_box_f().height();
276 break;
277 case ET_GESTURE_TWO_FINGER_TAP:
278 gesture.type = blink::WebInputEvent::GestureTwoFingerTap;
279 gesture.data.twoFingerTap.firstFingerWidth = details.first_finger_width();
280 gesture.data.twoFingerTap.firstFingerHeight =
281 details.first_finger_height();
282 break;
283 case ET_GESTURE_SCROLL_BEGIN:
284 gesture.type = WebInputEvent::GestureScrollBegin;
285 gesture.data.scrollBegin.deltaXHint = details.scroll_x_hint();
286 gesture.data.scrollBegin.deltaYHint = details.scroll_y_hint();
287 break;
288 case ET_GESTURE_SCROLL_UPDATE:
289 gesture.type = WebInputEvent::GestureScrollUpdate;
290 gesture.data.scrollUpdate.deltaX = details.scroll_x();
291 gesture.data.scrollUpdate.deltaY = details.scroll_y();
292 gesture.data.scrollUpdate.previousUpdateInSequencePrevented =
293 details.previous_scroll_update_in_sequence_prevented();
294 break;
295 case ET_GESTURE_SCROLL_END:
296 gesture.type = WebInputEvent::GestureScrollEnd;
297 break;
298 case ET_SCROLL_FLING_START:
299 gesture.type = WebInputEvent::GestureFlingStart;
300 gesture.data.flingStart.velocityX = details.velocity_x();
301 gesture.data.flingStart.velocityY = details.velocity_y();
302 break;
303 case ET_SCROLL_FLING_CANCEL:
304 gesture.type = WebInputEvent::GestureFlingCancel;
305 break;
306 case ET_GESTURE_PINCH_BEGIN:
307 gesture.type = WebInputEvent::GesturePinchBegin;
308 break;
309 case ET_GESTURE_PINCH_UPDATE:
310 gesture.type = WebInputEvent::GesturePinchUpdate;
311 gesture.data.pinchUpdate.scale = details.scale();
312 break;
313 case ET_GESTURE_PINCH_END:
314 gesture.type = WebInputEvent::GesturePinchEnd;
315 break;
316 case ET_GESTURE_TAP_CANCEL:
317 gesture.type = WebInputEvent::GestureTapCancel;
318 break;
319 case ET_GESTURE_TAP_DOWN:
320 gesture.type = WebInputEvent::GestureTapDown;
321 gesture.data.tapDown.width = details.bounding_box_f().width();
322 gesture.data.tapDown.height = details.bounding_box_f().height();
323 break;
324 case ET_GESTURE_BEGIN:
325 case ET_GESTURE_END:
326 case ET_GESTURE_SWIPE:
327 // The caller is responsible for discarding these gestures appropriately.
328 gesture.type = WebInputEvent::Undefined;
329 break;
330 default:
331 NOTREACHED() << "EventType provided wasn't a valid gesture event: "
332 << details.type();
335 return gesture;
338 WebGestureEvent CreateWebGestureEventFromGestureEventData(
339 const GestureEventData& data) {
340 return CreateWebGestureEvent(data.details, data.time - base::TimeTicks(),
341 gfx::PointF(data.x, data.y),
342 gfx::PointF(data.raw_x, data.raw_y), data.flags);
345 } // namespace ui