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 "third_party/WebKit/public/web/WebInputEvent.h"
8 #include "ui/events/event.h"
9 #include "ui/events/event_constants.h"
13 int WebModifiersToUIFlags(int modifiers
) {
14 int flags
= ui::EF_NONE
;
16 if (modifiers
& blink::WebInputEvent::ShiftKey
)
17 flags
|= ui::EF_SHIFT_DOWN
;
18 if (modifiers
& blink::WebInputEvent::ControlKey
)
19 flags
|= ui::EF_CONTROL_DOWN
;
20 if (modifiers
& blink::WebInputEvent::AltKey
)
21 flags
|= ui::EF_ALT_DOWN
;
23 if (modifiers
& blink::WebInputEvent::LeftButtonDown
)
24 flags
|= ui::EF_LEFT_MOUSE_BUTTON
;
25 if (modifiers
& blink::WebInputEvent::RightButtonDown
)
26 flags
|= ui::EF_RIGHT_MOUSE_BUTTON
;
27 if (modifiers
& blink::WebInputEvent::MiddleButtonDown
)
28 flags
|= ui::EF_MIDDLE_MOUSE_BUTTON
;
30 if (modifiers
& blink::WebInputEvent::CapsLockOn
)
31 flags
|= ui::EF_CAPS_LOCK_DOWN
;
36 ui::EventType
WebTouchPointStateToEventType(
37 blink::WebTouchPoint::State state
) {
39 case blink::WebTouchPoint::StateReleased
:
40 return ui::ET_TOUCH_RELEASED
;
42 case blink::WebTouchPoint::StatePressed
:
43 return ui::ET_TOUCH_PRESSED
;
45 case blink::WebTouchPoint::StateMoved
:
46 return ui::ET_TOUCH_MOVED
;
48 case blink::WebTouchPoint::StateCancelled
:
49 return ui::ET_TOUCH_CANCELLED
;
52 return ui::ET_UNKNOWN
;
56 blink::WebTouchPoint::State
TouchPointStateFromEvent(
57 const ui::TouchEvent
& event
) {
58 switch (event
.type()) {
59 case ui::ET_TOUCH_PRESSED
:
60 return blink::WebTouchPoint::StatePressed
;
61 case ui::ET_TOUCH_RELEASED
:
62 return blink::WebTouchPoint::StateReleased
;
63 case ui::ET_TOUCH_MOVED
:
64 return blink::WebTouchPoint::StateMoved
;
65 case ui::ET_TOUCH_CANCELLED
:
66 return blink::WebTouchPoint::StateCancelled
;
68 return blink::WebTouchPoint::StateUndefined
;
72 blink::WebInputEvent::Type
TouchEventTypeFromEvent(
73 const ui::TouchEvent
& event
) {
74 switch (event
.type()) {
75 case ui::ET_TOUCH_PRESSED
:
76 return blink::WebInputEvent::TouchStart
;
77 case ui::ET_TOUCH_RELEASED
:
78 return blink::WebInputEvent::TouchEnd
;
79 case ui::ET_TOUCH_MOVED
:
80 return blink::WebInputEvent::TouchMove
;
81 case ui::ET_TOUCH_CANCELLED
:
82 return blink::WebInputEvent::TouchCancel
;
84 return blink::WebInputEvent::Undefined
;
92 bool MakeUITouchEventsFromWebTouchEvents(
93 const TouchEventWithLatencyInfo
& touch_with_latency
,
94 ScopedVector
<ui::TouchEvent
>* list
,
95 TouchEventCoordinateSystem coordinate_system
) {
96 const blink::WebTouchEvent
& touch
= touch_with_latency
.event
;
97 ui::EventType type
= ui::ET_UNKNOWN
;
99 case blink::WebInputEvent::TouchStart
:
100 type
= ui::ET_TOUCH_PRESSED
;
102 case blink::WebInputEvent::TouchEnd
:
103 type
= ui::ET_TOUCH_RELEASED
;
105 case blink::WebInputEvent::TouchMove
:
106 type
= ui::ET_TOUCH_MOVED
;
108 case blink::WebInputEvent::TouchCancel
:
109 type
= ui::ET_TOUCH_CANCELLED
;
116 int flags
= WebModifiersToUIFlags(touch
.modifiers
);
117 base::TimeDelta timestamp
= base::TimeDelta::FromMicroseconds(
118 static_cast<int64
>(touch
.timeStampSeconds
* 1000000));
119 for (unsigned i
= 0; i
< touch
.touchesLength
; ++i
) {
120 const blink::WebTouchPoint
& point
= touch
.touches
[i
];
121 if (WebTouchPointStateToEventType(point
.state
) != type
)
123 // ui events start in the co-ordinate space of the EventDispatcher.
125 if (coordinate_system
== LOCAL_COORDINATES
)
126 location
= gfx::Point(point
.position
.x
, point
.position
.y
);
128 location
= gfx::Point(point
.screenPosition
.x
, point
.screenPosition
.y
);
129 ui::TouchEvent
* uievent
= new ui::TouchEvent(type
,
138 uievent
->set_latency(touch_with_latency
.latency
);
139 list
->push_back(uievent
);
144 blink::WebGestureEvent
MakeWebGestureEventFromUIEvent(
145 const ui::GestureEvent
& event
) {
146 blink::WebGestureEvent gesture_event
;
148 switch (event
.type()) {
149 case ui::ET_GESTURE_TAP
:
150 gesture_event
.type
= blink::WebInputEvent::GestureTap
;
151 gesture_event
.data
.tap
.tapCount
= event
.details().tap_count();
152 gesture_event
.data
.tap
.width
= event
.details().bounding_box().width();
153 gesture_event
.data
.tap
.height
= event
.details().bounding_box().height();
155 case ui::ET_GESTURE_TAP_DOWN
:
156 gesture_event
.type
= blink::WebInputEvent::GestureTapDown
;
157 gesture_event
.data
.tapDown
.width
=
158 event
.details().bounding_box().width();
159 gesture_event
.data
.tapDown
.height
=
160 event
.details().bounding_box().height();
162 case ui::ET_GESTURE_SHOW_PRESS
:
163 gesture_event
.type
= blink::WebInputEvent::GestureShowPress
;
164 gesture_event
.data
.showPress
.width
=
165 event
.details().bounding_box().width();
166 gesture_event
.data
.showPress
.height
=
167 event
.details().bounding_box().height();
169 case ui::ET_GESTURE_TAP_CANCEL
:
170 gesture_event
.type
= blink::WebInputEvent::GestureTapCancel
;
172 case ui::ET_GESTURE_SCROLL_BEGIN
:
173 gesture_event
.type
= blink::WebInputEvent::GestureScrollBegin
;
174 gesture_event
.data
.scrollBegin
.deltaXHint
=
175 event
.details().scroll_x_hint();
176 gesture_event
.data
.scrollBegin
.deltaYHint
=
177 event
.details().scroll_y_hint();
179 case ui::ET_GESTURE_SCROLL_UPDATE
:
180 gesture_event
.type
= blink::WebInputEvent::GestureScrollUpdate
;
181 gesture_event
.data
.scrollUpdate
.deltaX
= event
.details().scroll_x();
182 gesture_event
.data
.scrollUpdate
.deltaY
= event
.details().scroll_y();
184 case ui::ET_GESTURE_SCROLL_END
:
185 gesture_event
.type
= blink::WebInputEvent::GestureScrollEnd
;
187 case ui::ET_GESTURE_PINCH_BEGIN
:
188 gesture_event
.type
= blink::WebInputEvent::GesturePinchBegin
;
190 case ui::ET_GESTURE_PINCH_UPDATE
:
191 gesture_event
.type
= blink::WebInputEvent::GesturePinchUpdate
;
192 gesture_event
.data
.pinchUpdate
.scale
= event
.details().scale();
194 case ui::ET_GESTURE_PINCH_END
:
195 gesture_event
.type
= blink::WebInputEvent::GesturePinchEnd
;
197 case ui::ET_SCROLL_FLING_START
:
198 gesture_event
.type
= blink::WebInputEvent::GestureFlingStart
;
199 gesture_event
.data
.flingStart
.velocityX
= event
.details().velocity_x();
200 gesture_event
.data
.flingStart
.velocityY
= event
.details().velocity_y();
202 case ui::ET_SCROLL_FLING_CANCEL
:
203 gesture_event
.type
= blink::WebInputEvent::GestureFlingCancel
;
205 case ui::ET_GESTURE_LONG_PRESS
:
206 gesture_event
.type
= blink::WebInputEvent::GestureLongPress
;
207 gesture_event
.data
.longPress
.width
=
208 event
.details().bounding_box().width();
209 gesture_event
.data
.longPress
.height
=
210 event
.details().bounding_box().height();
212 case ui::ET_GESTURE_LONG_TAP
:
213 gesture_event
.type
= blink::WebInputEvent::GestureLongTap
;
214 gesture_event
.data
.longPress
.width
=
215 event
.details().bounding_box().width();
216 gesture_event
.data
.longPress
.height
=
217 event
.details().bounding_box().height();
219 case ui::ET_GESTURE_TWO_FINGER_TAP
:
220 gesture_event
.type
= blink::WebInputEvent::GestureTwoFingerTap
;
221 gesture_event
.data
.twoFingerTap
.firstFingerWidth
=
222 event
.details().first_finger_width();
223 gesture_event
.data
.twoFingerTap
.firstFingerHeight
=
224 event
.details().first_finger_height();
226 case ui::ET_GESTURE_BEGIN
:
227 case ui::ET_GESTURE_END
:
228 case ui::ET_GESTURE_MULTIFINGER_SWIPE
:
229 gesture_event
.type
= blink::WebInputEvent::Undefined
;
232 NOTREACHED() << "Unknown gesture type: " << event
.type();
235 gesture_event
.sourceDevice
= blink::WebGestureEvent::Touchscreen
;
236 gesture_event
.modifiers
= EventFlagsToWebEventModifiers(event
.flags());
237 gesture_event
.timeStampSeconds
= event
.time_stamp().InSecondsF();
239 return gesture_event
;
242 int EventFlagsToWebEventModifiers(int flags
) {
245 if (flags
& ui::EF_SHIFT_DOWN
)
246 modifiers
|= blink::WebInputEvent::ShiftKey
;
247 if (flags
& ui::EF_CONTROL_DOWN
)
248 modifiers
|= blink::WebInputEvent::ControlKey
;
249 if (flags
& ui::EF_ALT_DOWN
)
250 modifiers
|= blink::WebInputEvent::AltKey
;
251 // TODO(beng): MetaKey/META_MASK
252 if (flags
& ui::EF_LEFT_MOUSE_BUTTON
)
253 modifiers
|= blink::WebInputEvent::LeftButtonDown
;
254 if (flags
& ui::EF_MIDDLE_MOUSE_BUTTON
)
255 modifiers
|= blink::WebInputEvent::MiddleButtonDown
;
256 if (flags
& ui::EF_RIGHT_MOUSE_BUTTON
)
257 modifiers
|= blink::WebInputEvent::RightButtonDown
;
258 if (flags
& ui::EF_CAPS_LOCK_DOWN
)
259 modifiers
|= blink::WebInputEvent::CapsLockOn
;
263 blink::WebTouchPoint
* UpdateWebTouchEventFromUIEvent(
264 const ui::TouchEvent
& event
,
265 blink::WebTouchEvent
* web_event
) {
266 blink::WebTouchPoint
* point
= NULL
;
267 switch (event
.type()) {
268 case ui::ET_TOUCH_PRESSED
:
269 // Add a new touch point.
270 if (web_event
->touchesLength
< blink::WebTouchEvent::touchesLengthCap
) {
271 point
= &web_event
->touches
[web_event
->touchesLength
++];
272 point
->id
= event
.touch_id();
275 case ui::ET_TOUCH_RELEASED
:
276 case ui::ET_TOUCH_CANCELLED
:
277 case ui::ET_TOUCH_MOVED
: {
278 // The touch point should have been added to the event from an earlier
279 // _PRESSED event. So find that.
280 // At the moment, only a maximum of 4 touch-points are allowed. So a
281 // simple loop should be sufficient.
282 for (unsigned i
= 0; i
< web_event
->touchesLength
; ++i
) {
283 point
= web_event
->touches
+ i
;
284 if (point
->id
== event
.touch_id())
291 DLOG(WARNING
) << "Unknown touch event " << event
.type();
298 // The spec requires the radii values to be positive (and 1 when unknown).
299 point
->radiusX
= std::max(1.f
, event
.radius_x());
300 point
->radiusY
= std::max(1.f
, event
.radius_y());
301 point
->rotationAngle
= event
.rotation_angle();
302 point
->force
= event
.force();
304 // Update the location and state of the point.
305 point
->state
= TouchPointStateFromEvent(event
);
306 if (point
->state
== blink::WebTouchPoint::StateMoved
) {
307 // It is possible for badly written touch drivers to emit Move events even
308 // when the touch location hasn't changed. In such cases, consume the event
309 // and pretend nothing happened.
310 if (point
->position
.x
== event
.x() && point
->position
.y
== event
.y())
313 point
->position
.x
= event
.x();
314 point
->position
.y
= event
.y();
316 const gfx::Point root_point
= event
.root_location();
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 web_event
->type
= TouchEventTypeFromEvent(event
);
329 web_event
->timeStampSeconds
= event
.time_stamp().InSecondsF();
330 web_event
->modifiers
= EventFlagsToWebEventModifiers(event
.flags());
335 } // namespace content