Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / content / browser / renderer_host / input / web_input_event_util.cc
1 // Copyright 2013 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.
4
5 // MSVC++ requires this to be set before any other includes to get M_PI.
6 #define _USE_MATH_DEFINES
7
8 #include "content/browser/renderer_host/input/web_input_event_util.h"
9
10 #include <cmath>
11
12 #include "base/strings/string_util.h"
13 #include "content/common/input/web_touch_event_traits.h"
14 #include "ui/events/event_constants.h"
15 #include "ui/events/gesture_detection/gesture_event_data.h"
16 #include "ui/events/gesture_detection/motion_event.h"
17
18 using blink::WebGestureEvent;
19 using blink::WebInputEvent;
20 using blink::WebTouchEvent;
21 using blink::WebTouchPoint;
22 using ui::MotionEvent;
23
24 namespace {
25
26 const char* GetKeyIdentifier(ui::KeyboardCode key_code) {
27   switch (key_code) {
28     case ui::VKEY_MENU:
29       return "Alt";
30     case ui::VKEY_CONTROL:
31       return "Control";
32     case ui::VKEY_SHIFT:
33       return "Shift";
34     case ui::VKEY_CAPITAL:
35       return "CapsLock";
36     case ui::VKEY_LWIN:
37     case ui::VKEY_RWIN:
38       return "Win";
39     case ui::VKEY_CLEAR:
40       return "Clear";
41     case ui::VKEY_DOWN:
42       return "Down";
43     case ui::VKEY_END:
44       return "End";
45     case ui::VKEY_RETURN:
46       return "Enter";
47     case ui::VKEY_EXECUTE:
48       return "Execute";
49     case ui::VKEY_F1:
50       return "F1";
51     case ui::VKEY_F2:
52       return "F2";
53     case ui::VKEY_F3:
54       return "F3";
55     case ui::VKEY_F4:
56       return "F4";
57     case ui::VKEY_F5:
58       return "F5";
59     case ui::VKEY_F6:
60       return "F6";
61     case ui::VKEY_F7:
62       return "F7";
63     case ui::VKEY_F8:
64       return "F8";
65     case ui::VKEY_F9:
66       return "F9";
67     case ui::VKEY_F10:
68       return "F10";
69     case ui::VKEY_F11:
70       return "F11";
71     case ui::VKEY_F12:
72       return "F12";
73     case ui::VKEY_F13:
74       return "F13";
75     case ui::VKEY_F14:
76       return "F14";
77     case ui::VKEY_F15:
78       return "F15";
79     case ui::VKEY_F16:
80       return "F16";
81     case ui::VKEY_F17:
82       return "F17";
83     case ui::VKEY_F18:
84       return "F18";
85     case ui::VKEY_F19:
86       return "F19";
87     case ui::VKEY_F20:
88       return "F20";
89     case ui::VKEY_F21:
90       return "F21";
91     case ui::VKEY_F22:
92       return "F22";
93     case ui::VKEY_F23:
94       return "F23";
95     case ui::VKEY_F24:
96       return "F24";
97     case ui::VKEY_HELP:
98       return "Help";
99     case ui::VKEY_HOME:
100       return "Home";
101     case ui::VKEY_INSERT:
102       return "Insert";
103     case ui::VKEY_LEFT:
104       return "Left";
105     case ui::VKEY_NEXT:
106       return "PageDown";
107     case ui::VKEY_PRIOR:
108       return "PageUp";
109     case ui::VKEY_PAUSE:
110       return "Pause";
111     case ui::VKEY_SNAPSHOT:
112       return "PrintScreen";
113     case ui::VKEY_RIGHT:
114       return "Right";
115     case ui::VKEY_SCROLL:
116       return "Scroll";
117     case ui::VKEY_SELECT:
118       return "Select";
119     case ui::VKEY_UP:
120       return "Up";
121     case ui::VKEY_DELETE:
122       return "U+007F";  // Standard says that DEL becomes U+007F.
123     case ui::VKEY_MEDIA_NEXT_TRACK:
124       return "MediaNextTrack";
125     case ui::VKEY_MEDIA_PREV_TRACK:
126       return "MediaPreviousTrack";
127     case ui::VKEY_MEDIA_STOP:
128       return "MediaStop";
129     case ui::VKEY_MEDIA_PLAY_PAUSE:
130       return "MediaPlayPause";
131     case ui::VKEY_VOLUME_MUTE:
132       return "VolumeMute";
133     case ui::VKEY_VOLUME_DOWN:
134       return "VolumeDown";
135     case ui::VKEY_VOLUME_UP:
136       return "VolumeUp";
137     default:
138       return NULL;
139   };
140 }
141
142 WebInputEvent::Type ToWebInputEventType(MotionEvent::Action action) {
143   switch (action) {
144     case MotionEvent::ACTION_DOWN:
145       return WebInputEvent::TouchStart;
146     case MotionEvent::ACTION_MOVE:
147       return WebInputEvent::TouchMove;
148     case MotionEvent::ACTION_UP:
149       return WebInputEvent::TouchEnd;
150     case MotionEvent::ACTION_CANCEL:
151       return WebInputEvent::TouchCancel;
152     case MotionEvent::ACTION_POINTER_DOWN:
153       return WebInputEvent::TouchStart;
154     case MotionEvent::ACTION_POINTER_UP:
155       return WebInputEvent::TouchEnd;
156   }
157   NOTREACHED() << "Invalid MotionEvent::Action.";
158   return WebInputEvent::Undefined;
159 }
160
161 // Note that |is_action_pointer| is meaningful only in the context of
162 // |ACTION_POINTER_UP| and |ACTION_POINTER_DOWN|; other actions map directly to
163 // WebTouchPoint::State.
164 WebTouchPoint::State ToWebTouchPointState(MotionEvent::Action action,
165                                           bool is_action_pointer) {
166   switch (action) {
167     case MotionEvent::ACTION_DOWN:
168       return WebTouchPoint::StatePressed;
169     case MotionEvent::ACTION_MOVE:
170       return WebTouchPoint::StateMoved;
171     case MotionEvent::ACTION_UP:
172       return WebTouchPoint::StateReleased;
173     case MotionEvent::ACTION_CANCEL:
174       return WebTouchPoint::StateCancelled;
175     case MotionEvent::ACTION_POINTER_DOWN:
176       return is_action_pointer ? WebTouchPoint::StatePressed
177                                : WebTouchPoint::StateStationary;
178     case MotionEvent::ACTION_POINTER_UP:
179       return is_action_pointer ? WebTouchPoint::StateReleased
180                                : WebTouchPoint::StateStationary;
181   }
182   NOTREACHED() << "Invalid MotionEvent::Action.";
183   return WebTouchPoint::StateUndefined;
184 }
185
186 WebTouchPoint CreateWebTouchPoint(const MotionEvent& event,
187                                   size_t pointer_index) {
188   WebTouchPoint touch;
189   touch.id = event.GetPointerId(pointer_index);
190   touch.state = ToWebTouchPointState(
191       event.GetAction(),
192       static_cast<int>(pointer_index) == event.GetActionIndex());
193   touch.position.x = event.GetX(pointer_index);
194   touch.position.y = event.GetY(pointer_index);
195   touch.screenPosition.x = event.GetRawX(pointer_index);
196   touch.screenPosition.y = event.GetRawY(pointer_index);
197
198   // A note on touch ellipse specifications:
199   //
200   // Android MotionEvent provides the major and minor axes of the touch ellipse,
201   // as well as the orientation of the major axis clockwise from vertical, in
202   // radians. See:
203   // http://developer.android.com/reference/android/view/MotionEvent.html
204   //
205   // The proposed extension to W3C Touch Events specifies the touch ellipse
206   // using two radii along x- & y-axes and a positive acute rotation angle in
207   // degrees. See:
208   // http://dvcs.w3.org/hg/webevents/raw-file/default/touchevents.html
209
210   float major_radius = event.GetTouchMajor(pointer_index) / 2.f;
211   float minor_radius = event.GetTouchMinor(pointer_index) / 2.f;
212   float orientation_deg = event.GetOrientation(pointer_index) * 180.f / M_PI;
213   DCHECK_GE(major_radius, 0);
214   DCHECK_GE(minor_radius, 0);
215   DCHECK_GE(major_radius, minor_radius);
216   // Allow a small bound tolerance to account for floating point conversion.
217   DCHECK_GT(orientation_deg, -90.01f);
218   DCHECK_LT(orientation_deg, 90.01f);
219   if (orientation_deg >= 0) {
220     // The case orientation_deg == 0 is handled here on purpose: although the
221     // 'else' block is equivalent in this case, we want to pass the 0 value
222     // unchanged (and 0 is the default value for many devices that don't
223     // report elliptical touches).
224     touch.radiusX = minor_radius;
225     touch.radiusY = major_radius;
226     touch.rotationAngle = orientation_deg;
227   } else {
228     touch.radiusX = major_radius;
229     touch.radiusY = minor_radius;
230     touch.rotationAngle = orientation_deg + 90;
231   }
232
233   touch.force = event.GetPressure(pointer_index);
234
235   return touch;
236 }
237
238 }  // namespace
239
240 namespace content {
241
242 void UpdateWindowsKeyCodeAndKeyIdentifier(blink::WebKeyboardEvent* event,
243                                           ui::KeyboardCode windows_key_code) {
244   event->windowsKeyCode = windows_key_code;
245
246   const char* id = GetKeyIdentifier(windows_key_code);
247   if (id) {
248     base::strlcpy(event->keyIdentifier, id, sizeof(event->keyIdentifier) - 1);
249   } else {
250     base::snprintf(event->keyIdentifier,
251                    sizeof(event->keyIdentifier),
252                    "U+%04X",
253                    base::ToUpperASCII(static_cast<int>(windows_key_code)));
254   }
255 }
256
257 blink::WebTouchEvent CreateWebTouchEventFromMotionEvent(
258     const ui::MotionEvent& event) {
259   COMPILE_ASSERT(static_cast<int>(MotionEvent::MAX_TOUCH_POINT_COUNT) ==
260                      static_cast<int>(blink::WebTouchEvent::touchesLengthCap),
261                  inconsistent_maximum_number_of_active_touch_points);
262
263   blink::WebTouchEvent result;
264
265   WebTouchEventTraits::ResetType(
266       ToWebInputEventType(event.GetAction()),
267       (event.GetEventTime() - base::TimeTicks()).InSecondsF(),
268       &result);
269
270   result.modifiers = EventFlagsToWebEventModifiers(event.GetFlags());
271   result.touchesLength =
272       std::min(event.GetPointerCount(),
273                static_cast<size_t>(WebTouchEvent::touchesLengthCap));
274   DCHECK_GT(result.touchesLength, 0U);
275
276   for (size_t i = 0; i < result.touchesLength; ++i)
277     result.touches[i] = CreateWebTouchPoint(event, i);
278
279   return result;
280 }
281
282 WebGestureEvent CreateWebGestureEventFromGestureEventData(
283     const ui::GestureEventData& data) {
284   WebGestureEvent gesture;
285   gesture.modifiers = EventFlagsToWebEventModifiers(data.flags);
286   gesture.x = data.x;
287   gesture.y = data.y;
288   gesture.globalX = data.raw_x;
289   gesture.globalY = data.raw_y;
290   gesture.timeStampSeconds = (data.time - base::TimeTicks()).InSecondsF();
291   gesture.sourceDevice = blink::WebGestureDeviceTouchscreen;
292
293   switch (data.type()) {
294     case ui::ET_GESTURE_SHOW_PRESS:
295       gesture.type = WebInputEvent::GestureShowPress;
296       gesture.data.showPress.width = data.details.bounding_box_f().width();
297       gesture.data.showPress.height = data.details.bounding_box_f().height();
298       break;
299     case ui::ET_GESTURE_DOUBLE_TAP:
300       gesture.type = WebInputEvent::GestureDoubleTap;
301       DCHECK_EQ(1, data.details.tap_count());
302       gesture.data.tap.tapCount = data.details.tap_count();
303       gesture.data.tap.width = data.details.bounding_box_f().width();
304       gesture.data.tap.height = data.details.bounding_box_f().height();
305       break;
306     case ui::ET_GESTURE_TAP:
307       gesture.type = WebInputEvent::GestureTap;
308       DCHECK_EQ(1, data.details.tap_count());
309       gesture.data.tap.tapCount = data.details.tap_count();
310       gesture.data.tap.width = data.details.bounding_box_f().width();
311       gesture.data.tap.height = data.details.bounding_box_f().height();
312       break;
313     case ui::ET_GESTURE_TAP_UNCONFIRMED:
314       gesture.type = WebInputEvent::GestureTapUnconfirmed;
315       DCHECK_EQ(1, data.details.tap_count());
316       gesture.data.tap.tapCount = data.details.tap_count();
317       gesture.data.tap.width = data.details.bounding_box_f().width();
318       gesture.data.tap.height = data.details.bounding_box_f().height();
319       break;
320     case ui::ET_GESTURE_LONG_PRESS:
321       gesture.type = WebInputEvent::GestureLongPress;
322       gesture.data.longPress.width = data.details.bounding_box_f().width();
323       gesture.data.longPress.height = data.details.bounding_box_f().height();
324       break;
325     case ui::ET_GESTURE_LONG_TAP:
326       gesture.type = WebInputEvent::GestureLongTap;
327       gesture.data.longPress.width = data.details.bounding_box_f().width();
328       gesture.data.longPress.height = data.details.bounding_box_f().height();
329       break;
330     case ui::ET_GESTURE_SCROLL_BEGIN:
331       gesture.type = WebInputEvent::GestureScrollBegin;
332       gesture.data.scrollBegin.deltaXHint = data.details.scroll_x_hint();
333       gesture.data.scrollBegin.deltaYHint = data.details.scroll_y_hint();
334       break;
335     case ui::ET_GESTURE_SCROLL_UPDATE:
336       gesture.type = WebInputEvent::GestureScrollUpdate;
337       gesture.data.scrollUpdate.deltaX = data.details.scroll_x();
338       gesture.data.scrollUpdate.deltaY = data.details.scroll_y();
339       break;
340     case ui::ET_GESTURE_SCROLL_END:
341       gesture.type = WebInputEvent::GestureScrollEnd;
342       break;
343     case ui::ET_SCROLL_FLING_START:
344       gesture.type = WebInputEvent::GestureFlingStart;
345       gesture.data.flingStart.velocityX = data.details.velocity_x();
346       gesture.data.flingStart.velocityY = data.details.velocity_y();
347       break;
348     case ui::ET_SCROLL_FLING_CANCEL:
349       gesture.type = WebInputEvent::GestureFlingCancel;
350       break;
351     case ui::ET_GESTURE_PINCH_BEGIN:
352       gesture.type = WebInputEvent::GesturePinchBegin;
353       break;
354     case ui::ET_GESTURE_PINCH_UPDATE:
355       gesture.type = WebInputEvent::GesturePinchUpdate;
356       gesture.data.pinchUpdate.scale = data.details.scale();
357       break;
358     case ui::ET_GESTURE_PINCH_END:
359       gesture.type = WebInputEvent::GesturePinchEnd;
360       break;
361     case ui::ET_GESTURE_TAP_CANCEL:
362       gesture.type = WebInputEvent::GestureTapCancel;
363       break;
364     case ui::ET_GESTURE_TAP_DOWN:
365       gesture.type = WebInputEvent::GestureTapDown;
366       gesture.data.tapDown.width = data.details.bounding_box_f().width();
367       gesture.data.tapDown.height = data.details.bounding_box_f().height();
368       break;
369     case ui::ET_GESTURE_BEGIN:
370     case ui::ET_GESTURE_END:
371       NOTREACHED() << "ET_GESTURE_BEGIN and ET_GESTURE_END are only produced "
372                    << "in Aura, and should never end up here.";
373       break;
374     default:
375       NOTREACHED() << "ui::EventType provided wasn't a valid gesture event.";
376       break;
377   }
378
379   return gesture;
380 }
381
382 int EventFlagsToWebEventModifiers(int flags) {
383   int modifiers = 0;
384
385   if (flags & ui::EF_SHIFT_DOWN)
386     modifiers |= blink::WebInputEvent::ShiftKey;
387   if (flags & ui::EF_CONTROL_DOWN)
388     modifiers |= blink::WebInputEvent::ControlKey;
389   if (flags & ui::EF_ALT_DOWN)
390     modifiers |= blink::WebInputEvent::AltKey;
391   if (flags & ui::EF_COMMAND_DOWN)
392     modifiers |= blink::WebInputEvent::MetaKey;
393
394   if (flags & ui::EF_LEFT_MOUSE_BUTTON)
395     modifiers |= blink::WebInputEvent::LeftButtonDown;
396   if (flags & ui::EF_MIDDLE_MOUSE_BUTTON)
397     modifiers |= blink::WebInputEvent::MiddleButtonDown;
398   if (flags & ui::EF_RIGHT_MOUSE_BUTTON)
399     modifiers |= blink::WebInputEvent::RightButtonDown;
400   if (flags & ui::EF_CAPS_LOCK_DOWN)
401     modifiers |= blink::WebInputEvent::CapsLockOn;
402   if (flags & ui::EF_IS_REPEAT)
403     modifiers |= blink::WebInputEvent::IsAutoRepeat;
404   if (flags & ui::EF_NUMPAD_KEY)
405     modifiers |= blink::WebInputEvent::IsKeyPad;
406
407   return modifiers;
408 }
409
410 int WebEventModifiersToEventFlags(int modifiers) {
411   int flags = 0;
412
413   if (modifiers & blink::WebInputEvent::ShiftKey)
414     flags |= ui::EF_SHIFT_DOWN;
415   if (modifiers & blink::WebInputEvent::ControlKey)
416     flags |= ui::EF_CONTROL_DOWN;
417   if (modifiers & blink::WebInputEvent::AltKey)
418     flags |= ui::EF_ALT_DOWN;
419   if (modifiers & blink::WebInputEvent::MetaKey)
420     flags |= ui::EF_COMMAND_DOWN;
421
422   if (modifiers & blink::WebInputEvent::LeftButtonDown)
423     flags |= ui::EF_LEFT_MOUSE_BUTTON;
424   if (modifiers & blink::WebInputEvent::MiddleButtonDown)
425     flags |= ui::EF_MIDDLE_MOUSE_BUTTON;
426   if (modifiers & blink::WebInputEvent::RightButtonDown)
427     flags |= ui::EF_RIGHT_MOUSE_BUTTON;
428   if (modifiers & blink::WebInputEvent::CapsLockOn)
429     flags |= ui::EF_CAPS_LOCK_DOWN;
430   if (modifiers & blink::WebInputEvent::IsAutoRepeat)
431     flags |= ui::EF_IS_REPEAT;
432   if (modifiers & blink::WebInputEvent::IsKeyPad)
433     flags |= ui::EF_NUMPAD_KEY;
434
435   return flags;
436 }
437
438 }  // namespace content