• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "content/browser/renderer_host/input/web_input_event_util.h"
6 
7 #include "base/strings/string_util.h"
8 #include "content/common/input/web_touch_event_traits.h"
9 #include "ui/events/gesture_detection/gesture_event_data.h"
10 #include "ui/events/gesture_detection/motion_event.h"
11 
12 using blink::WebGestureEvent;
13 using blink::WebInputEvent;
14 using blink::WebTouchEvent;
15 using blink::WebTouchPoint;
16 using ui::MotionEvent;
17 
18 namespace {
19 
GetKeyIdentifier(ui::KeyboardCode key_code)20 const char* GetKeyIdentifier(ui::KeyboardCode key_code) {
21   switch (key_code) {
22     case ui::VKEY_MENU:
23       return "Alt";
24     case ui::VKEY_CONTROL:
25       return "Control";
26     case ui::VKEY_SHIFT:
27       return "Shift";
28     case ui::VKEY_CAPITAL:
29       return "CapsLock";
30     case ui::VKEY_LWIN:
31     case ui::VKEY_RWIN:
32       return "Win";
33     case ui::VKEY_CLEAR:
34       return "Clear";
35     case ui::VKEY_DOWN:
36       return "Down";
37     case ui::VKEY_END:
38       return "End";
39     case ui::VKEY_RETURN:
40       return "Enter";
41     case ui::VKEY_EXECUTE:
42       return "Execute";
43     case ui::VKEY_F1:
44       return "F1";
45     case ui::VKEY_F2:
46       return "F2";
47     case ui::VKEY_F3:
48       return "F3";
49     case ui::VKEY_F4:
50       return "F4";
51     case ui::VKEY_F5:
52       return "F5";
53     case ui::VKEY_F6:
54       return "F6";
55     case ui::VKEY_F7:
56       return "F7";
57     case ui::VKEY_F8:
58       return "F8";
59     case ui::VKEY_F9:
60       return "F9";
61     case ui::VKEY_F10:
62       return "F10";
63     case ui::VKEY_F11:
64       return "F11";
65     case ui::VKEY_F12:
66       return "F12";
67     case ui::VKEY_F13:
68       return "F13";
69     case ui::VKEY_F14:
70       return "F14";
71     case ui::VKEY_F15:
72       return "F15";
73     case ui::VKEY_F16:
74       return "F16";
75     case ui::VKEY_F17:
76       return "F17";
77     case ui::VKEY_F18:
78       return "F18";
79     case ui::VKEY_F19:
80       return "F19";
81     case ui::VKEY_F20:
82       return "F20";
83     case ui::VKEY_F21:
84       return "F21";
85     case ui::VKEY_F22:
86       return "F22";
87     case ui::VKEY_F23:
88       return "F23";
89     case ui::VKEY_F24:
90       return "F24";
91     case ui::VKEY_HELP:
92       return "Help";
93     case ui::VKEY_HOME:
94       return "Home";
95     case ui::VKEY_INSERT:
96       return "Insert";
97     case ui::VKEY_LEFT:
98       return "Left";
99     case ui::VKEY_NEXT:
100       return "PageDown";
101     case ui::VKEY_PRIOR:
102       return "PageUp";
103     case ui::VKEY_PAUSE:
104       return "Pause";
105     case ui::VKEY_SNAPSHOT:
106       return "PrintScreen";
107     case ui::VKEY_RIGHT:
108       return "Right";
109     case ui::VKEY_SCROLL:
110       return "Scroll";
111     case ui::VKEY_SELECT:
112       return "Select";
113     case ui::VKEY_UP:
114       return "Up";
115     case ui::VKEY_DELETE:
116       return "U+007F";  // Standard says that DEL becomes U+007F.
117     case ui::VKEY_MEDIA_NEXT_TRACK:
118       return "MediaNextTrack";
119     case ui::VKEY_MEDIA_PREV_TRACK:
120       return "MediaPreviousTrack";
121     case ui::VKEY_MEDIA_STOP:
122       return "MediaStop";
123     case ui::VKEY_MEDIA_PLAY_PAUSE:
124       return "MediaPlayPause";
125     case ui::VKEY_VOLUME_MUTE:
126       return "VolumeMute";
127     case ui::VKEY_VOLUME_DOWN:
128       return "VolumeDown";
129     case ui::VKEY_VOLUME_UP:
130       return "VolumeUp";
131     default:
132       return NULL;
133   };
134 }
135 
ToWebInputEventType(MotionEvent::Action action)136 WebInputEvent::Type ToWebInputEventType(MotionEvent::Action action) {
137   switch (action) {
138     case MotionEvent::ACTION_DOWN:
139       return WebInputEvent::TouchStart;
140     case MotionEvent::ACTION_MOVE:
141       return WebInputEvent::TouchMove;
142     case MotionEvent::ACTION_UP:
143       return WebInputEvent::TouchEnd;
144     case MotionEvent::ACTION_CANCEL:
145       return WebInputEvent::TouchCancel;
146     case MotionEvent::ACTION_POINTER_DOWN:
147       return WebInputEvent::TouchStart;
148     case MotionEvent::ACTION_POINTER_UP:
149       return WebInputEvent::TouchEnd;
150   }
151   NOTREACHED() << "Invalid MotionEvent::Action.";
152   return WebInputEvent::Undefined;
153 }
154 
155 // Note that |is_action_pointer| is meaningful only in the context of
156 // |ACTION_POINTER_UP| and |ACTION_POINTER_DOWN|; other actions map directly to
157 // WebTouchPoint::State.
ToWebTouchPointState(MotionEvent::Action action,bool is_action_pointer)158 WebTouchPoint::State ToWebTouchPointState(MotionEvent::Action action,
159                                           bool is_action_pointer) {
160   switch (action) {
161     case MotionEvent::ACTION_DOWN:
162       return WebTouchPoint::StatePressed;
163     case MotionEvent::ACTION_MOVE:
164       return WebTouchPoint::StateMoved;
165     case MotionEvent::ACTION_UP:
166       return WebTouchPoint::StateReleased;
167     case MotionEvent::ACTION_CANCEL:
168       return WebTouchPoint::StateCancelled;
169     case MotionEvent::ACTION_POINTER_DOWN:
170       return is_action_pointer ? WebTouchPoint::StatePressed
171                                : WebTouchPoint::StateStationary;
172     case MotionEvent::ACTION_POINTER_UP:
173       return is_action_pointer ? WebTouchPoint::StateReleased
174                                : WebTouchPoint::StateStationary;
175   }
176   NOTREACHED() << "Invalid MotionEvent::Action.";
177   return WebTouchPoint::StateUndefined;
178 }
179 
CreateWebTouchPoint(const MotionEvent & event,size_t pointer_index)180 WebTouchPoint CreateWebTouchPoint(const MotionEvent& event,
181                                   size_t pointer_index) {
182   WebTouchPoint touch;
183   touch.id = event.GetPointerId(pointer_index);
184   touch.state = ToWebTouchPointState(
185       event.GetAction(),
186       static_cast<int>(pointer_index) == event.GetActionIndex());
187   touch.position.x = event.GetX(pointer_index);
188   touch.position.y = event.GetY(pointer_index);
189   touch.screenPosition.x = event.GetRawX(pointer_index);
190   touch.screenPosition.y = event.GetRawY(pointer_index);
191   touch.radiusX = touch.radiusY = event.GetTouchMajor(pointer_index) * 0.5f;
192   touch.force = event.GetPressure(pointer_index);
193 
194   return touch;
195 }
196 
197 }  // namespace
198 
199 namespace content {
200 
UpdateWindowsKeyCodeAndKeyIdentifier(blink::WebKeyboardEvent * event,ui::KeyboardCode windows_key_code)201 void UpdateWindowsKeyCodeAndKeyIdentifier(blink::WebKeyboardEvent* event,
202                                           ui::KeyboardCode windows_key_code) {
203   event->windowsKeyCode = windows_key_code;
204 
205   const char* id = GetKeyIdentifier(windows_key_code);
206   if (id) {
207     base::strlcpy(event->keyIdentifier, id, sizeof(event->keyIdentifier) - 1);
208   } else {
209     base::snprintf(event->keyIdentifier,
210                    sizeof(event->keyIdentifier),
211                    "U+%04X",
212                    base::ToUpperASCII(static_cast<int>(windows_key_code)));
213   }
214 }
215 
CreateWebTouchEventFromMotionEvent(const ui::MotionEvent & event)216 blink::WebTouchEvent CreateWebTouchEventFromMotionEvent(
217     const ui::MotionEvent& event) {
218   blink::WebTouchEvent result;
219 
220   WebTouchEventTraits::ResetType(
221       ToWebInputEventType(event.GetAction()),
222       (event.GetEventTime() - base::TimeTicks()).InSecondsF(),
223       &result);
224 
225   result.touchesLength =
226       std::min(event.GetPointerCount(),
227                static_cast<size_t>(WebTouchEvent::touchesLengthCap));
228   DCHECK_GT(result.touchesLength, 0U);
229 
230   for (size_t i = 0; i < result.touchesLength; ++i)
231     result.touches[i] = CreateWebTouchPoint(event, i);
232 
233   return result;
234 }
235 
CreateWebGestureEventFromGestureEventData(const ui::GestureEventData & data)236 WebGestureEvent CreateWebGestureEventFromGestureEventData(
237     const ui::GestureEventData& data) {
238   WebGestureEvent gesture;
239   gesture.x = data.x;
240   gesture.y = data.y;
241   gesture.globalX = data.raw_x;
242   gesture.globalY = data.raw_y;
243   gesture.timeStampSeconds = (data.time - base::TimeTicks()).InSecondsF();
244   gesture.sourceDevice = blink::WebGestureDeviceTouchscreen;
245 
246   switch (data.type()) {
247     case ui::ET_GESTURE_SHOW_PRESS:
248       gesture.type = WebInputEvent::GestureShowPress;
249       gesture.data.showPress.width = data.details.bounding_box_f().width();
250       gesture.data.showPress.height = data.details.bounding_box_f().height();
251       break;
252     case ui::ET_GESTURE_DOUBLE_TAP:
253       gesture.type = WebInputEvent::GestureDoubleTap;
254       DCHECK_EQ(1, data.details.tap_count());
255       gesture.data.tap.tapCount = data.details.tap_count();
256       gesture.data.tap.width = data.details.bounding_box_f().width();
257       gesture.data.tap.height = data.details.bounding_box_f().height();
258       break;
259     case ui::ET_GESTURE_TAP:
260       gesture.type = WebInputEvent::GestureTap;
261       DCHECK_EQ(1, data.details.tap_count());
262       gesture.data.tap.tapCount = data.details.tap_count();
263       gesture.data.tap.width = data.details.bounding_box_f().width();
264       gesture.data.tap.height = data.details.bounding_box_f().height();
265       break;
266     case ui::ET_GESTURE_TAP_UNCONFIRMED:
267       gesture.type = WebInputEvent::GestureTapUnconfirmed;
268       DCHECK_EQ(1, data.details.tap_count());
269       gesture.data.tap.tapCount = data.details.tap_count();
270       gesture.data.tap.width = data.details.bounding_box_f().width();
271       gesture.data.tap.height = data.details.bounding_box_f().height();
272       break;
273     case ui::ET_GESTURE_LONG_PRESS:
274       gesture.type = WebInputEvent::GestureLongPress;
275       gesture.data.longPress.width = data.details.bounding_box_f().width();
276       gesture.data.longPress.height = data.details.bounding_box_f().height();
277       break;
278     case ui::ET_GESTURE_LONG_TAP:
279       gesture.type = WebInputEvent::GestureLongTap;
280       gesture.data.longPress.width = data.details.bounding_box_f().width();
281       gesture.data.longPress.height = data.details.bounding_box_f().height();
282       break;
283     case ui::ET_GESTURE_SCROLL_BEGIN:
284       gesture.type = WebInputEvent::GestureScrollBegin;
285       gesture.data.scrollBegin.deltaXHint = data.details.scroll_x_hint();
286       gesture.data.scrollBegin.deltaYHint = data.details.scroll_y_hint();
287       break;
288     case ui::ET_GESTURE_SCROLL_UPDATE:
289       gesture.type = WebInputEvent::GestureScrollUpdate;
290       gesture.data.scrollUpdate.deltaX = data.details.scroll_x();
291       gesture.data.scrollUpdate.deltaY = data.details.scroll_y();
292       break;
293     case ui::ET_GESTURE_SCROLL_END:
294       gesture.type = WebInputEvent::GestureScrollEnd;
295       break;
296     case ui::ET_SCROLL_FLING_START:
297       gesture.type = WebInputEvent::GestureFlingStart;
298       gesture.data.flingStart.velocityX = data.details.velocity_x();
299       gesture.data.flingStart.velocityY = data.details.velocity_y();
300       break;
301     case ui::ET_SCROLL_FLING_CANCEL:
302       gesture.type = WebInputEvent::GestureFlingCancel;
303       break;
304     case ui::ET_GESTURE_PINCH_BEGIN:
305       gesture.type = WebInputEvent::GesturePinchBegin;
306       break;
307     case ui::ET_GESTURE_PINCH_UPDATE:
308       gesture.type = WebInputEvent::GesturePinchUpdate;
309       gesture.data.pinchUpdate.scale = data.details.scale();
310       break;
311     case ui::ET_GESTURE_PINCH_END:
312       gesture.type = WebInputEvent::GesturePinchEnd;
313       break;
314     case ui::ET_GESTURE_TAP_CANCEL:
315       gesture.type = WebInputEvent::GestureTapCancel;
316       break;
317     case ui::ET_GESTURE_TAP_DOWN:
318       gesture.type = WebInputEvent::GestureTapDown;
319       gesture.data.tapDown.width = data.details.bounding_box_f().width();
320       gesture.data.tapDown.height = data.details.bounding_box_f().height();
321       break;
322     case ui::ET_GESTURE_BEGIN:
323     case ui::ET_GESTURE_END:
324       NOTREACHED() << "ET_GESTURE_BEGIN and ET_GESTURE_END are only produced "
325                    << "in Aura, and should never end up here.";
326       break;
327     default:
328       NOTREACHED() << "ui::EventType provided wasn't a valid gesture event.";
329       break;
330   }
331 
332   return gesture;
333 }
334 
335 }  // namespace content
336