1 // Copyright (c) 2012 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 #include "content/browser/renderer_host/ui_events_helper.h"
7 #include "content/common/input/web_touch_event_traits.h"
8 #include "third_party/WebKit/public/web/WebInputEvent.h"
9 #include "ui/events/event.h"
10 #include "ui/events/event_constants.h"
14 int WebModifiersToUIFlags(int modifiers
) {
15 int flags
= ui::EF_NONE
;
17 if (modifiers
& blink::WebInputEvent::ShiftKey
)
18 flags
|= ui::EF_SHIFT_DOWN
;
19 if (modifiers
& blink::WebInputEvent::ControlKey
)
20 flags
|= ui::EF_CONTROL_DOWN
;
21 if (modifiers
& blink::WebInputEvent::AltKey
)
22 flags
|= ui::EF_ALT_DOWN
;
23 if (modifiers
& blink::WebInputEvent::MetaKey
)
24 flags
|= ui::EF_COMMAND_DOWN
;
26 if (modifiers
& blink::WebInputEvent::LeftButtonDown
)
27 flags
|= ui::EF_LEFT_MOUSE_BUTTON
;
28 if (modifiers
& blink::WebInputEvent::RightButtonDown
)
29 flags
|= ui::EF_RIGHT_MOUSE_BUTTON
;
30 if (modifiers
& blink::WebInputEvent::MiddleButtonDown
)
31 flags
|= ui::EF_MIDDLE_MOUSE_BUTTON
;
33 if (modifiers
& blink::WebInputEvent::CapsLockOn
)
34 flags
|= ui::EF_CAPS_LOCK_DOWN
;
39 ui::EventType
WebTouchPointStateToEventType(
40 blink::WebTouchPoint::State state
) {
42 case blink::WebTouchPoint::StateReleased
:
43 return ui::ET_TOUCH_RELEASED
;
45 case blink::WebTouchPoint::StatePressed
:
46 return ui::ET_TOUCH_PRESSED
;
48 case blink::WebTouchPoint::StateMoved
:
49 return ui::ET_TOUCH_MOVED
;
51 case blink::WebTouchPoint::StateCancelled
:
52 return ui::ET_TOUCH_CANCELLED
;
55 return ui::ET_UNKNOWN
;
59 blink::WebTouchPoint::State
TouchPointStateFromEvent(
60 const ui::TouchEvent
& event
) {
61 switch (event
.type()) {
62 case ui::ET_TOUCH_PRESSED
:
63 return blink::WebTouchPoint::StatePressed
;
64 case ui::ET_TOUCH_RELEASED
:
65 return blink::WebTouchPoint::StateReleased
;
66 case ui::ET_TOUCH_MOVED
:
67 return blink::WebTouchPoint::StateMoved
;
68 case ui::ET_TOUCH_CANCELLED
:
69 return blink::WebTouchPoint::StateCancelled
;
71 return blink::WebTouchPoint::StateUndefined
;
75 blink::WebInputEvent::Type
TouchEventTypeFromEvent(
76 const ui::TouchEvent
& event
) {
77 switch (event
.type()) {
78 case ui::ET_TOUCH_PRESSED
:
79 return blink::WebInputEvent::TouchStart
;
80 case ui::ET_TOUCH_RELEASED
:
81 return blink::WebInputEvent::TouchEnd
;
82 case ui::ET_TOUCH_MOVED
:
83 return blink::WebInputEvent::TouchMove
;
84 case ui::ET_TOUCH_CANCELLED
:
85 return blink::WebInputEvent::TouchCancel
;
87 return blink::WebInputEvent::Undefined
;
95 bool MakeUITouchEventsFromWebTouchEvents(
96 const TouchEventWithLatencyInfo
& touch_with_latency
,
97 ScopedVector
<ui::TouchEvent
>* list
,
98 TouchEventCoordinateSystem coordinate_system
) {
99 const blink::WebTouchEvent
& touch
= touch_with_latency
.event
;
100 ui::EventType type
= ui::ET_UNKNOWN
;
101 switch (touch
.type
) {
102 case blink::WebInputEvent::TouchStart
:
103 type
= ui::ET_TOUCH_PRESSED
;
105 case blink::WebInputEvent::TouchEnd
:
106 type
= ui::ET_TOUCH_RELEASED
;
108 case blink::WebInputEvent::TouchMove
:
109 type
= ui::ET_TOUCH_MOVED
;
111 case blink::WebInputEvent::TouchCancel
:
112 type
= ui::ET_TOUCH_CANCELLED
;
119 int flags
= WebModifiersToUIFlags(touch
.modifiers
);
120 base::TimeDelta timestamp
= base::TimeDelta::FromMicroseconds(
121 static_cast<int64
>(touch
.timeStampSeconds
* 1000000));
122 for (unsigned i
= 0; i
< touch
.touchesLength
; ++i
) {
123 const blink::WebTouchPoint
& point
= touch
.touches
[i
];
124 if (WebTouchPointStateToEventType(point
.state
) != type
)
126 // ui events start in the co-ordinate space of the EventDispatcher.
127 gfx::PointF location
;
128 if (coordinate_system
== LOCAL_COORDINATES
)
129 location
= point
.position
;
131 location
= point
.screenPosition
;
132 ui::TouchEvent
* uievent
= new ui::TouchEvent(type
,
141 uievent
->set_latency(touch_with_latency
.latency
);
142 list
->push_back(uievent
);
147 blink::WebGestureEvent
MakeWebGestureEventFromUIEvent(
148 const ui::GestureEvent
& event
) {
149 blink::WebGestureEvent gesture_event
;
151 switch (event
.type()) {
152 case ui::ET_GESTURE_TAP
:
153 gesture_event
.type
= blink::WebInputEvent::GestureTap
;
154 gesture_event
.data
.tap
.tapCount
= event
.details().tap_count();
155 gesture_event
.data
.tap
.width
= event
.details().bounding_box().width();
156 gesture_event
.data
.tap
.height
= event
.details().bounding_box().height();
158 case ui::ET_GESTURE_TAP_DOWN
:
159 gesture_event
.type
= blink::WebInputEvent::GestureTapDown
;
160 gesture_event
.data
.tapDown
.width
=
161 event
.details().bounding_box().width();
162 gesture_event
.data
.tapDown
.height
=
163 event
.details().bounding_box().height();
165 case ui::ET_GESTURE_SHOW_PRESS
:
166 gesture_event
.type
= blink::WebInputEvent::GestureShowPress
;
167 gesture_event
.data
.showPress
.width
=
168 event
.details().bounding_box().width();
169 gesture_event
.data
.showPress
.height
=
170 event
.details().bounding_box().height();
172 case ui::ET_GESTURE_TAP_CANCEL
:
173 gesture_event
.type
= blink::WebInputEvent::GestureTapCancel
;
175 case ui::ET_GESTURE_SCROLL_BEGIN
:
176 gesture_event
.type
= blink::WebInputEvent::GestureScrollBegin
;
177 gesture_event
.data
.scrollBegin
.deltaXHint
=
178 event
.details().scroll_x_hint();
179 gesture_event
.data
.scrollBegin
.deltaYHint
=
180 event
.details().scroll_y_hint();
182 case ui::ET_GESTURE_SCROLL_UPDATE
:
183 gesture_event
.type
= blink::WebInputEvent::GestureScrollUpdate
;
184 gesture_event
.data
.scrollUpdate
.deltaX
= event
.details().scroll_x();
185 gesture_event
.data
.scrollUpdate
.deltaY
= event
.details().scroll_y();
187 case ui::ET_GESTURE_SCROLL_END
:
188 gesture_event
.type
= blink::WebInputEvent::GestureScrollEnd
;
190 case ui::ET_GESTURE_PINCH_BEGIN
:
191 gesture_event
.type
= blink::WebInputEvent::GesturePinchBegin
;
193 case ui::ET_GESTURE_PINCH_UPDATE
:
194 gesture_event
.type
= blink::WebInputEvent::GesturePinchUpdate
;
195 gesture_event
.data
.pinchUpdate
.scale
= event
.details().scale();
197 case ui::ET_GESTURE_PINCH_END
:
198 gesture_event
.type
= blink::WebInputEvent::GesturePinchEnd
;
200 case ui::ET_SCROLL_FLING_START
:
201 gesture_event
.type
= blink::WebInputEvent::GestureFlingStart
;
202 gesture_event
.data
.flingStart
.velocityX
= event
.details().velocity_x();
203 gesture_event
.data
.flingStart
.velocityY
= event
.details().velocity_y();
205 case ui::ET_SCROLL_FLING_CANCEL
:
206 gesture_event
.type
= blink::WebInputEvent::GestureFlingCancel
;
208 case ui::ET_GESTURE_LONG_PRESS
:
209 gesture_event
.type
= blink::WebInputEvent::GestureLongPress
;
210 gesture_event
.data
.longPress
.width
=
211 event
.details().bounding_box().width();
212 gesture_event
.data
.longPress
.height
=
213 event
.details().bounding_box().height();
215 case ui::ET_GESTURE_LONG_TAP
:
216 gesture_event
.type
= blink::WebInputEvent::GestureLongTap
;
217 gesture_event
.data
.longPress
.width
=
218 event
.details().bounding_box().width();
219 gesture_event
.data
.longPress
.height
=
220 event
.details().bounding_box().height();
222 case ui::ET_GESTURE_TWO_FINGER_TAP
:
223 gesture_event
.type
= blink::WebInputEvent::GestureTwoFingerTap
;
224 gesture_event
.data
.twoFingerTap
.firstFingerWidth
=
225 event
.details().first_finger_width();
226 gesture_event
.data
.twoFingerTap
.firstFingerHeight
=
227 event
.details().first_finger_height();
229 case ui::ET_GESTURE_BEGIN
:
230 case ui::ET_GESTURE_END
:
231 case ui::ET_GESTURE_SWIPE
:
232 gesture_event
.type
= blink::WebInputEvent::Undefined
;
235 NOTREACHED() << "Unknown gesture type: " << event
.type();
238 gesture_event
.sourceDevice
= blink::WebGestureDeviceTouchscreen
;
239 gesture_event
.modifiers
= EventFlagsToWebEventModifiers(event
.flags());
240 gesture_event
.timeStampSeconds
= event
.time_stamp().InSecondsF();
242 return gesture_event
;
245 int EventFlagsToWebEventModifiers(int flags
) {
248 if (flags
& ui::EF_SHIFT_DOWN
)
249 modifiers
|= blink::WebInputEvent::ShiftKey
;
250 if (flags
& ui::EF_CONTROL_DOWN
)
251 modifiers
|= blink::WebInputEvent::ControlKey
;
252 if (flags
& ui::EF_ALT_DOWN
)
253 modifiers
|= blink::WebInputEvent::AltKey
;
254 if (flags
& ui::EF_COMMAND_DOWN
)
255 modifiers
|= blink::WebInputEvent::MetaKey
;
257 if (flags
& ui::EF_LEFT_MOUSE_BUTTON
)
258 modifiers
|= blink::WebInputEvent::LeftButtonDown
;
259 if (flags
& ui::EF_MIDDLE_MOUSE_BUTTON
)
260 modifiers
|= blink::WebInputEvent::MiddleButtonDown
;
261 if (flags
& ui::EF_RIGHT_MOUSE_BUTTON
)
262 modifiers
|= blink::WebInputEvent::RightButtonDown
;
263 if (flags
& ui::EF_CAPS_LOCK_DOWN
)
264 modifiers
|= blink::WebInputEvent::CapsLockOn
;
265 if (flags
& ui::EF_IS_REPEAT
)
266 modifiers
|= blink::WebInputEvent::IsAutoRepeat
;
270 blink::WebTouchPoint
* UpdateWebTouchEventFromUIEvent(
271 const ui::TouchEvent
& event
,
272 blink::WebTouchEvent
* web_event
) {
273 blink::WebTouchPoint
* point
= NULL
;
274 switch (event
.type()) {
275 case ui::ET_TOUCH_PRESSED
:
276 // Add a new touch point.
277 if (web_event
->touchesLength
< blink::WebTouchEvent::touchesLengthCap
) {
278 point
= &web_event
->touches
[web_event
->touchesLength
++];
279 point
->id
= event
.touch_id();
282 case ui::ET_TOUCH_RELEASED
:
283 case ui::ET_TOUCH_CANCELLED
:
284 case ui::ET_TOUCH_MOVED
: {
285 // The touch point should have been added to the event from an earlier
286 // _PRESSED event. So find that.
287 // At the moment, only a maximum of 4 touch-points are allowed. So a
288 // simple loop should be sufficient.
289 for (unsigned i
= 0; i
< web_event
->touchesLength
; ++i
) {
290 point
= web_event
->touches
+ i
;
291 if (point
->id
== event
.touch_id())
298 DLOG(WARNING
) << "Unknown touch event " << event
.type();
305 // The spec requires the radii values to be positive (and 1 when unknown).
306 point
->radiusX
= std::max(1.f
, event
.radius_x());
307 point
->radiusY
= std::max(1.f
, event
.radius_y());
308 point
->rotationAngle
= event
.rotation_angle();
309 point
->force
= event
.force();
311 // Update the location and state of the point.
312 point
->state
= TouchPointStateFromEvent(event
);
313 point
->position
.x
= event
.x();
314 point
->position
.y
= event
.y();
316 const gfx::PointF
& root_point
= event
.root_location_f();
317 point
->screenPosition
.x
= root_point
.x();
318 point
->screenPosition
.y
= root_point
.y();
320 // Mark the rest of the points as stationary.
321 for (unsigned i
= 0; i
< web_event
->touchesLength
; ++i
) {
322 blink::WebTouchPoint
* iter
= web_event
->touches
+ i
;
324 iter
->state
= blink::WebTouchPoint::StateStationary
;
327 // Update the type of the touch event.
328 WebTouchEventTraits::ResetType(TouchEventTypeFromEvent(event
),
329 event
.time_stamp().InSecondsF(),
331 web_event
->modifiers
= EventFlagsToWebEventModifiers(event
.flags());
336 } // namespace content