Battery Status API: add UMA logging for Linux.
[chromium-blink-merge.git] / content / browser / renderer_host / ui_events_helper.cc
blob7208b76c36323aee83b5146f94d17728d63441b5
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"
12 namespace {
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;
36 return flags;
39 ui::EventType WebTouchPointStateToEventType(
40 blink::WebTouchPoint::State state) {
41 switch (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;
54 default:
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;
70 default:
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;
86 default:
87 return blink::WebInputEvent::Undefined;
91 } // namespace
93 namespace content {
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;
104 break;
105 case blink::WebInputEvent::TouchEnd:
106 type = ui::ET_TOUCH_RELEASED;
107 break;
108 case blink::WebInputEvent::TouchMove:
109 type = ui::ET_TOUCH_MOVED;
110 break;
111 case blink::WebInputEvent::TouchCancel:
112 type = ui::ET_TOUCH_CANCELLED;
113 break;
114 default:
115 NOTREACHED();
116 return false;
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)
125 continue;
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;
130 else
131 location = point.screenPosition;
132 ui::TouchEvent* uievent = new ui::TouchEvent(type,
133 location,
134 flags,
135 point.id,
136 timestamp,
137 point.radiusX,
138 point.radiusY,
139 point.rotationAngle,
140 point.force);
141 uievent->set_latency(touch_with_latency.latency);
142 list->push_back(uievent);
144 return true;
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();
157 break;
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();
164 break;
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();
171 break;
172 case ui::ET_GESTURE_TAP_CANCEL:
173 gesture_event.type = blink::WebInputEvent::GestureTapCancel;
174 break;
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();
181 break;
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();
186 break;
187 case ui::ET_GESTURE_SCROLL_END:
188 gesture_event.type = blink::WebInputEvent::GestureScrollEnd;
189 break;
190 case ui::ET_GESTURE_PINCH_BEGIN:
191 gesture_event.type = blink::WebInputEvent::GesturePinchBegin;
192 break;
193 case ui::ET_GESTURE_PINCH_UPDATE:
194 gesture_event.type = blink::WebInputEvent::GesturePinchUpdate;
195 gesture_event.data.pinchUpdate.scale = event.details().scale();
196 break;
197 case ui::ET_GESTURE_PINCH_END:
198 gesture_event.type = blink::WebInputEvent::GesturePinchEnd;
199 break;
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();
204 break;
205 case ui::ET_SCROLL_FLING_CANCEL:
206 gesture_event.type = blink::WebInputEvent::GestureFlingCancel;
207 break;
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();
214 break;
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();
221 break;
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();
228 break;
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;
233 break;
234 default:
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) {
246 int modifiers = 0;
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;
267 return modifiers;
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();
281 break;
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())
292 break;
293 point = NULL;
295 break;
297 default:
298 DLOG(WARNING) << "Unknown touch event " << event.type();
299 break;
302 if (!point)
303 return NULL;
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;
323 if (iter != point)
324 iter->state = blink::WebTouchPoint::StateStationary;
327 // Update the type of the touch event.
328 WebTouchEventTraits::ResetType(TouchEventTypeFromEvent(event),
329 event.time_stamp().InSecondsF(),
330 web_event);
331 web_event->modifiers = EventFlagsToWebEventModifiers(event.flags());
333 return point;
336 } // namespace content