IndexedDBFactory now ForceCloses databases.
[chromium-blink-merge.git] / content / browser / renderer_host / ui_events_helper.cc
blobe5af6c174ad5485de95669d7be1d11188931ae94
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"
11 namespace {
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;
33 return flags;
36 ui::EventType WebTouchPointStateToEventType(
37 blink::WebTouchPoint::State state) {
38 switch (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;
51 default:
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;
67 default:
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;
83 default:
84 return blink::WebInputEvent::Undefined;
88 } // namespace
90 namespace content {
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;
98 switch (touch.type) {
99 case blink::WebInputEvent::TouchStart:
100 type = ui::ET_TOUCH_PRESSED;
101 break;
102 case blink::WebInputEvent::TouchEnd:
103 type = ui::ET_TOUCH_RELEASED;
104 break;
105 case blink::WebInputEvent::TouchMove:
106 type = ui::ET_TOUCH_MOVED;
107 break;
108 case blink::WebInputEvent::TouchCancel:
109 type = ui::ET_TOUCH_CANCELLED;
110 break;
111 default:
112 NOTREACHED();
113 return false;
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)
122 continue;
123 // In aura, the touch-event needs to be in the screen coordinate, since the
124 // touch-event is routed to RootWindow first. In Windows, on the other hand,
125 // the touch-event is dispatched directly to the gesture-recognizer, so the
126 // location needs to be in the local coordinate space.
127 #if defined(USE_AURA)
128 gfx::Point location;
129 if (coordinate_system == LOCAL_COORDINATES)
130 location = gfx::Point(point.position.x, point.position.y);
131 else
132 location = gfx::Point(point.screenPosition.x, point.screenPosition.y);
133 #else
134 gfx::Point location(point.position.x, point.position.y);
135 #endif
136 ui::TouchEvent* uievent = new ui::TouchEvent(type,
137 location,
138 flags,
139 point.id,
140 timestamp,
141 point.radiusX,
142 point.radiusY,
143 point.rotationAngle,
144 point.force);
145 uievent->set_latency(touch_with_latency.latency);
146 list->push_back(uievent);
148 return true;
151 blink::WebGestureEvent MakeWebGestureEventFromUIEvent(
152 const ui::GestureEvent& event) {
153 blink::WebGestureEvent gesture_event;
155 switch (event.type()) {
156 case ui::ET_GESTURE_TAP:
157 gesture_event.type = blink::WebInputEvent::GestureTap;
158 gesture_event.data.tap.tapCount = event.details().tap_count();
159 gesture_event.data.tap.width = event.details().bounding_box().width();
160 gesture_event.data.tap.height = event.details().bounding_box().height();
161 break;
162 case ui::ET_GESTURE_TAP_DOWN:
163 gesture_event.type = blink::WebInputEvent::GestureTapDown;
164 gesture_event.data.tapDown.width =
165 event.details().bounding_box().width();
166 gesture_event.data.tapDown.height =
167 event.details().bounding_box().height();
168 break;
169 case ui::ET_GESTURE_SHOW_PRESS:
170 gesture_event.type = blink::WebInputEvent::GestureShowPress;
171 gesture_event.data.showPress.width =
172 event.details().bounding_box().width();
173 gesture_event.data.showPress.height =
174 event.details().bounding_box().height();
175 break;
176 case ui::ET_GESTURE_TAP_CANCEL:
177 gesture_event.type = blink::WebInputEvent::GestureTapCancel;
178 break;
179 case ui::ET_GESTURE_SCROLL_BEGIN:
180 gesture_event.type = blink::WebInputEvent::GestureScrollBegin;
181 gesture_event.data.scrollBegin.deltaXHint =
182 event.details().scroll_x_hint();
183 gesture_event.data.scrollBegin.deltaYHint =
184 event.details().scroll_y_hint();
185 break;
186 case ui::ET_GESTURE_SCROLL_UPDATE:
187 gesture_event.type = blink::WebInputEvent::GestureScrollUpdate;
188 gesture_event.data.scrollUpdate.deltaX = event.details().scroll_x();
189 gesture_event.data.scrollUpdate.deltaY = event.details().scroll_y();
190 break;
191 case ui::ET_GESTURE_SCROLL_END:
192 gesture_event.type = blink::WebInputEvent::GestureScrollEnd;
193 break;
194 case ui::ET_GESTURE_PINCH_BEGIN:
195 gesture_event.type = blink::WebInputEvent::GesturePinchBegin;
196 break;
197 case ui::ET_GESTURE_PINCH_UPDATE:
198 gesture_event.type = blink::WebInputEvent::GesturePinchUpdate;
199 gesture_event.data.pinchUpdate.scale = event.details().scale();
200 break;
201 case ui::ET_GESTURE_PINCH_END:
202 gesture_event.type = blink::WebInputEvent::GesturePinchEnd;
203 break;
204 case ui::ET_SCROLL_FLING_START:
205 gesture_event.type = blink::WebInputEvent::GestureFlingStart;
206 gesture_event.data.flingStart.velocityX = event.details().velocity_x();
207 gesture_event.data.flingStart.velocityY = event.details().velocity_y();
208 break;
209 case ui::ET_SCROLL_FLING_CANCEL:
210 gesture_event.type = blink::WebInputEvent::GestureFlingCancel;
211 break;
212 case ui::ET_GESTURE_LONG_PRESS:
213 gesture_event.type = blink::WebInputEvent::GestureLongPress;
214 gesture_event.data.longPress.width =
215 event.details().bounding_box().width();
216 gesture_event.data.longPress.height =
217 event.details().bounding_box().height();
218 break;
219 case ui::ET_GESTURE_LONG_TAP:
220 gesture_event.type = blink::WebInputEvent::GestureLongTap;
221 gesture_event.data.longPress.width =
222 event.details().bounding_box().width();
223 gesture_event.data.longPress.height =
224 event.details().bounding_box().height();
225 break;
226 case ui::ET_GESTURE_TWO_FINGER_TAP:
227 gesture_event.type = blink::WebInputEvent::GestureTwoFingerTap;
228 gesture_event.data.twoFingerTap.firstFingerWidth =
229 event.details().first_finger_width();
230 gesture_event.data.twoFingerTap.firstFingerHeight =
231 event.details().first_finger_height();
232 break;
233 case ui::ET_GESTURE_BEGIN:
234 case ui::ET_GESTURE_END:
235 case ui::ET_GESTURE_MULTIFINGER_SWIPE:
236 gesture_event.type = blink::WebInputEvent::Undefined;
237 break;
238 default:
239 NOTREACHED() << "Unknown gesture type: " << event.type();
242 gesture_event.sourceDevice = blink::WebGestureEvent::Touchscreen;
243 gesture_event.modifiers = EventFlagsToWebEventModifiers(event.flags());
244 gesture_event.timeStampSeconds = event.time_stamp().InSecondsF();
246 return gesture_event;
249 int EventFlagsToWebEventModifiers(int flags) {
250 int modifiers = 0;
252 if (flags & ui::EF_SHIFT_DOWN)
253 modifiers |= blink::WebInputEvent::ShiftKey;
254 if (flags & ui::EF_CONTROL_DOWN)
255 modifiers |= blink::WebInputEvent::ControlKey;
256 if (flags & ui::EF_ALT_DOWN)
257 modifiers |= blink::WebInputEvent::AltKey;
258 // TODO(beng): MetaKey/META_MASK
259 if (flags & ui::EF_LEFT_MOUSE_BUTTON)
260 modifiers |= blink::WebInputEvent::LeftButtonDown;
261 if (flags & ui::EF_MIDDLE_MOUSE_BUTTON)
262 modifiers |= blink::WebInputEvent::MiddleButtonDown;
263 if (flags & ui::EF_RIGHT_MOUSE_BUTTON)
264 modifiers |= blink::WebInputEvent::RightButtonDown;
265 if (flags & ui::EF_CAPS_LOCK_DOWN)
266 modifiers |= blink::WebInputEvent::CapsLockOn;
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 if (point->state == blink::WebTouchPoint::StateMoved) {
314 // It is possible for badly written touch drivers to emit Move events even
315 // when the touch location hasn't changed. In such cases, consume the event
316 // and pretend nothing happened.
317 if (point->position.x == event.x() && point->position.y == event.y())
318 return NULL;
320 point->position.x = event.x();
321 point->position.y = event.y();
323 const gfx::Point root_point = event.root_location();
324 point->screenPosition.x = root_point.x();
325 point->screenPosition.y = root_point.y();
327 // Mark the rest of the points as stationary.
328 for (unsigned i = 0; i < web_event->touchesLength; ++i) {
329 blink::WebTouchPoint* iter = web_event->touches + i;
330 if (iter != point)
331 iter->state = blink::WebTouchPoint::StateStationary;
334 // Update the type of the touch event.
335 web_event->type = TouchEventTypeFromEvent(event);
336 web_event->timeStampSeconds = event.time_stamp().InSecondsF();
337 web_event->modifiers = EventFlagsToWebEventModifiers(event.flags());
339 return point;
342 } // namespace content