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/browser/renderer_host/input/web_input_event_util.h"
8 #include "content/common/input/web_touch_event_traits.h"
9 #include "third_party/WebKit/public/web/WebInputEvent.h"
10 #include "ui/events/event.h"
11 #include "ui/events/event_constants.h"
15 int WebModifiersToUIFlags(int modifiers
) {
16 int flags
= ui::EF_NONE
;
18 if (modifiers
& blink::WebInputEvent::ShiftKey
)
19 flags
|= ui::EF_SHIFT_DOWN
;
20 if (modifiers
& blink::WebInputEvent::ControlKey
)
21 flags
|= ui::EF_CONTROL_DOWN
;
22 if (modifiers
& blink::WebInputEvent::AltKey
)
23 flags
|= ui::EF_ALT_DOWN
;
24 if (modifiers
& blink::WebInputEvent::MetaKey
)
25 flags
|= ui::EF_COMMAND_DOWN
;
27 if (modifiers
& blink::WebInputEvent::LeftButtonDown
)
28 flags
|= ui::EF_LEFT_MOUSE_BUTTON
;
29 if (modifiers
& blink::WebInputEvent::RightButtonDown
)
30 flags
|= ui::EF_RIGHT_MOUSE_BUTTON
;
31 if (modifiers
& blink::WebInputEvent::MiddleButtonDown
)
32 flags
|= ui::EF_MIDDLE_MOUSE_BUTTON
;
34 if (modifiers
& blink::WebInputEvent::CapsLockOn
)
35 flags
|= ui::EF_CAPS_LOCK_DOWN
;
40 ui::EventType
WebTouchPointStateToEventType(
41 blink::WebTouchPoint::State state
) {
43 case blink::WebTouchPoint::StateReleased
:
44 return ui::ET_TOUCH_RELEASED
;
46 case blink::WebTouchPoint::StatePressed
:
47 return ui::ET_TOUCH_PRESSED
;
49 case blink::WebTouchPoint::StateMoved
:
50 return ui::ET_TOUCH_MOVED
;
52 case blink::WebTouchPoint::StateCancelled
:
53 return ui::ET_TOUCH_CANCELLED
;
56 return ui::ET_UNKNOWN
;
60 blink::WebTouchPoint::State
TouchPointStateFromEvent(
61 const ui::TouchEvent
& event
) {
62 switch (event
.type()) {
63 case ui::ET_TOUCH_PRESSED
:
64 return blink::WebTouchPoint::StatePressed
;
65 case ui::ET_TOUCH_RELEASED
:
66 return blink::WebTouchPoint::StateReleased
;
67 case ui::ET_TOUCH_MOVED
:
68 return blink::WebTouchPoint::StateMoved
;
69 case ui::ET_TOUCH_CANCELLED
:
70 return blink::WebTouchPoint::StateCancelled
;
72 return blink::WebTouchPoint::StateUndefined
;
76 blink::WebInputEvent::Type
TouchEventTypeFromEvent(
77 const ui::TouchEvent
& event
) {
78 switch (event
.type()) {
79 case ui::ET_TOUCH_PRESSED
:
80 return blink::WebInputEvent::TouchStart
;
81 case ui::ET_TOUCH_RELEASED
:
82 return blink::WebInputEvent::TouchEnd
;
83 case ui::ET_TOUCH_MOVED
:
84 return blink::WebInputEvent::TouchMove
;
85 case ui::ET_TOUCH_CANCELLED
:
86 return blink::WebInputEvent::TouchCancel
;
88 return blink::WebInputEvent::Undefined
;
96 bool MakeUITouchEventsFromWebTouchEvents(
97 const TouchEventWithLatencyInfo
& touch_with_latency
,
98 ScopedVector
<ui::TouchEvent
>* list
,
99 TouchEventCoordinateSystem coordinate_system
) {
100 const blink::WebTouchEvent
& touch
= touch_with_latency
.event
;
101 ui::EventType type
= ui::ET_UNKNOWN
;
102 switch (touch
.type
) {
103 case blink::WebInputEvent::TouchStart
:
104 type
= ui::ET_TOUCH_PRESSED
;
106 case blink::WebInputEvent::TouchEnd
:
107 type
= ui::ET_TOUCH_RELEASED
;
109 case blink::WebInputEvent::TouchMove
:
110 type
= ui::ET_TOUCH_MOVED
;
112 case blink::WebInputEvent::TouchCancel
:
113 type
= ui::ET_TOUCH_CANCELLED
;
120 int flags
= WebModifiersToUIFlags(touch
.modifiers
);
121 base::TimeDelta timestamp
= base::TimeDelta::FromMicroseconds(
122 static_cast<int64
>(touch
.timeStampSeconds
* 1000000));
123 for (unsigned i
= 0; i
< touch
.touchesLength
; ++i
) {
124 const blink::WebTouchPoint
& point
= touch
.touches
[i
];
125 if (WebTouchPointStateToEventType(point
.state
) != type
)
127 // ui events start in the co-ordinate space of the EventDispatcher.
128 gfx::PointF location
;
129 if (coordinate_system
== LOCAL_COORDINATES
)
130 location
= point
.position
;
132 location
= point
.screenPosition
;
133 ui::TouchEvent
* uievent
= new ui::TouchEvent(type
,
142 uievent
->set_latency(touch_with_latency
.latency
);
143 list
->push_back(uievent
);
148 blink::WebGestureEvent
MakeWebGestureEventFromUIEvent(
149 const ui::GestureEvent
& event
) {
150 blink::WebGestureEvent gesture_event
;
152 switch (event
.type()) {
153 case ui::ET_GESTURE_TAP
:
154 gesture_event
.type
= blink::WebInputEvent::GestureTap
;
155 gesture_event
.data
.tap
.tapCount
= event
.details().tap_count();
156 gesture_event
.data
.tap
.width
= event
.details().bounding_box().width();
157 gesture_event
.data
.tap
.height
= event
.details().bounding_box().height();
159 case ui::ET_GESTURE_TAP_DOWN
:
160 gesture_event
.type
= blink::WebInputEvent::GestureTapDown
;
161 gesture_event
.data
.tapDown
.width
=
162 event
.details().bounding_box().width();
163 gesture_event
.data
.tapDown
.height
=
164 event
.details().bounding_box().height();
166 case ui::ET_GESTURE_SHOW_PRESS
:
167 gesture_event
.type
= blink::WebInputEvent::GestureShowPress
;
168 gesture_event
.data
.showPress
.width
=
169 event
.details().bounding_box().width();
170 gesture_event
.data
.showPress
.height
=
171 event
.details().bounding_box().height();
173 case ui::ET_GESTURE_TAP_CANCEL
:
174 gesture_event
.type
= blink::WebInputEvent::GestureTapCancel
;
176 case ui::ET_GESTURE_SCROLL_BEGIN
:
177 gesture_event
.type
= blink::WebInputEvent::GestureScrollBegin
;
178 gesture_event
.data
.scrollBegin
.deltaXHint
=
179 event
.details().scroll_x_hint();
180 gesture_event
.data
.scrollBegin
.deltaYHint
=
181 event
.details().scroll_y_hint();
183 case ui::ET_GESTURE_SCROLL_UPDATE
:
184 gesture_event
.type
= blink::WebInputEvent::GestureScrollUpdate
;
185 gesture_event
.data
.scrollUpdate
.deltaX
= event
.details().scroll_x();
186 gesture_event
.data
.scrollUpdate
.deltaY
= event
.details().scroll_y();
188 case ui::ET_GESTURE_SCROLL_END
:
189 gesture_event
.type
= blink::WebInputEvent::GestureScrollEnd
;
191 case ui::ET_GESTURE_PINCH_BEGIN
:
192 gesture_event
.type
= blink::WebInputEvent::GesturePinchBegin
;
194 case ui::ET_GESTURE_PINCH_UPDATE
:
195 gesture_event
.type
= blink::WebInputEvent::GesturePinchUpdate
;
196 gesture_event
.data
.pinchUpdate
.scale
= event
.details().scale();
198 case ui::ET_GESTURE_PINCH_END
:
199 gesture_event
.type
= blink::WebInputEvent::GesturePinchEnd
;
201 case ui::ET_SCROLL_FLING_START
:
202 gesture_event
.type
= blink::WebInputEvent::GestureFlingStart
;
203 gesture_event
.data
.flingStart
.velocityX
= event
.details().velocity_x();
204 gesture_event
.data
.flingStart
.velocityY
= event
.details().velocity_y();
206 case ui::ET_SCROLL_FLING_CANCEL
:
207 gesture_event
.type
= blink::WebInputEvent::GestureFlingCancel
;
209 case ui::ET_GESTURE_LONG_PRESS
:
210 gesture_event
.type
= blink::WebInputEvent::GestureLongPress
;
211 gesture_event
.data
.longPress
.width
=
212 event
.details().bounding_box().width();
213 gesture_event
.data
.longPress
.height
=
214 event
.details().bounding_box().height();
216 case ui::ET_GESTURE_LONG_TAP
:
217 gesture_event
.type
= blink::WebInputEvent::GestureLongTap
;
218 gesture_event
.data
.longPress
.width
=
219 event
.details().bounding_box().width();
220 gesture_event
.data
.longPress
.height
=
221 event
.details().bounding_box().height();
223 case ui::ET_GESTURE_TWO_FINGER_TAP
:
224 gesture_event
.type
= blink::WebInputEvent::GestureTwoFingerTap
;
225 gesture_event
.data
.twoFingerTap
.firstFingerWidth
=
226 event
.details().first_finger_width();
227 gesture_event
.data
.twoFingerTap
.firstFingerHeight
=
228 event
.details().first_finger_height();
230 case ui::ET_GESTURE_BEGIN
:
231 case ui::ET_GESTURE_END
:
232 case ui::ET_GESTURE_SWIPE
:
233 gesture_event
.type
= blink::WebInputEvent::Undefined
;
236 NOTREACHED() << "Unknown gesture type: " << event
.type();
239 gesture_event
.sourceDevice
= blink::WebGestureDeviceTouchscreen
;
240 gesture_event
.modifiers
= EventFlagsToWebEventModifiers(event
.flags());
241 gesture_event
.timeStampSeconds
= event
.time_stamp().InSecondsF();
243 return gesture_event
;
246 blink::WebTouchPoint
* UpdateWebTouchEventFromUIEvent(
247 const ui::TouchEvent
& event
,
248 blink::WebTouchEvent
* web_event
) {
249 blink::WebTouchPoint
* point
= NULL
;
250 switch (event
.type()) {
251 case ui::ET_TOUCH_PRESSED
:
252 // Add a new touch point.
253 if (web_event
->touchesLength
< blink::WebTouchEvent::touchesLengthCap
) {
254 point
= &web_event
->touches
[web_event
->touchesLength
++];
255 point
->id
= event
.touch_id();
258 case ui::ET_TOUCH_RELEASED
:
259 case ui::ET_TOUCH_CANCELLED
:
260 case ui::ET_TOUCH_MOVED
: {
261 // The touch point should have been added to the event from an earlier
262 // _PRESSED event. So find that.
263 // At the moment, only a maximum of 4 touch-points are allowed. So a
264 // simple loop should be sufficient.
265 for (unsigned i
= 0; i
< web_event
->touchesLength
; ++i
) {
266 point
= web_event
->touches
+ i
;
267 if (point
->id
== event
.touch_id())
274 DLOG(WARNING
) << "Unknown touch event " << event
.type();
281 // The spec requires the radii values to be positive (and 1 when unknown).
282 point
->radiusX
= std::max(1.f
, event
.radius_x());
283 point
->radiusY
= std::max(1.f
, event
.radius_y());
284 point
->rotationAngle
= event
.rotation_angle();
285 point
->force
= event
.force();
287 // Update the location and state of the point.
288 point
->state
= TouchPointStateFromEvent(event
);
289 point
->position
.x
= event
.x();
290 point
->position
.y
= event
.y();
292 const gfx::PointF
& root_point
= event
.root_location_f();
293 point
->screenPosition
.x
= root_point
.x();
294 point
->screenPosition
.y
= root_point
.y();
296 // Mark the rest of the points as stationary.
297 for (unsigned i
= 0; i
< web_event
->touchesLength
; ++i
) {
298 blink::WebTouchPoint
* iter
= web_event
->touches
+ i
;
300 iter
->state
= blink::WebTouchPoint::StateStationary
;
303 // Update the type of the touch event.
304 WebTouchEventTraits::ResetType(TouchEventTypeFromEvent(event
),
305 event
.time_stamp().InSecondsF(),
307 web_event
->modifiers
= EventFlagsToWebEventModifiers(event
.flags());
312 } // namespace content