cc: Make picture pile base thread safe.
[chromium-blink-merge.git] / content / browser / renderer_host / ui_events_helper.cc
blobb514425cc883eb83852c8c22101eea58b156c162
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"
13 namespace {
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;
37 return flags;
40 ui::EventType WebTouchPointStateToEventType(
41 blink::WebTouchPoint::State state) {
42 switch (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;
55 default:
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;
71 default:
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;
87 default:
88 return blink::WebInputEvent::Undefined;
92 } // namespace
94 namespace content {
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;
105 break;
106 case blink::WebInputEvent::TouchEnd:
107 type = ui::ET_TOUCH_RELEASED;
108 break;
109 case blink::WebInputEvent::TouchMove:
110 type = ui::ET_TOUCH_MOVED;
111 break;
112 case blink::WebInputEvent::TouchCancel:
113 type = ui::ET_TOUCH_CANCELLED;
114 break;
115 default:
116 NOTREACHED();
117 return false;
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)
126 continue;
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;
131 else
132 location = point.screenPosition;
133 ui::TouchEvent* uievent = new ui::TouchEvent(type,
134 location,
135 flags,
136 point.id,
137 timestamp,
138 point.radiusX,
139 point.radiusY,
140 point.rotationAngle,
141 point.force);
142 uievent->set_latency(touch_with_latency.latency);
143 list->push_back(uievent);
145 return true;
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();
158 break;
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();
165 break;
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();
172 break;
173 case ui::ET_GESTURE_TAP_CANCEL:
174 gesture_event.type = blink::WebInputEvent::GestureTapCancel;
175 break;
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();
182 break;
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();
187 break;
188 case ui::ET_GESTURE_SCROLL_END:
189 gesture_event.type = blink::WebInputEvent::GestureScrollEnd;
190 break;
191 case ui::ET_GESTURE_PINCH_BEGIN:
192 gesture_event.type = blink::WebInputEvent::GesturePinchBegin;
193 break;
194 case ui::ET_GESTURE_PINCH_UPDATE:
195 gesture_event.type = blink::WebInputEvent::GesturePinchUpdate;
196 gesture_event.data.pinchUpdate.scale = event.details().scale();
197 break;
198 case ui::ET_GESTURE_PINCH_END:
199 gesture_event.type = blink::WebInputEvent::GesturePinchEnd;
200 break;
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();
205 break;
206 case ui::ET_SCROLL_FLING_CANCEL:
207 gesture_event.type = blink::WebInputEvent::GestureFlingCancel;
208 break;
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();
215 break;
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();
222 break;
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();
229 break;
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;
234 break;
235 default:
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();
257 break;
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())
268 break;
269 point = NULL;
271 break;
273 default:
274 DLOG(WARNING) << "Unknown touch event " << event.type();
275 break;
278 if (!point)
279 return NULL;
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;
299 if (iter != point)
300 iter->state = blink::WebTouchPoint::StateStationary;
303 // Update the type of the touch event.
304 WebTouchEventTraits::ResetType(TouchEventTypeFromEvent(event),
305 event.time_stamp().InSecondsF(),
306 web_event);
307 web_event->modifiers = EventFlagsToWebEventModifiers(event.flags());
309 return point;
312 } // namespace content