Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / content / browser / renderer_host / input / web_input_event_builders_android.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 #include "content/browser/renderer_host/input/web_input_event_builders_android.h"
6
7 #include "base/logging.h"
8 #include "content/browser/renderer_host/input/motion_event_android.h"
9 #include "content/browser/renderer_host/input/web_input_event_util.h"
10 #include "content/browser/renderer_host/input/web_input_event_util_posix.h"
11 #include "ui/events/keycodes/keyboard_code_conversion_android.h"
12 #include "ui/events/keycodes/keyboard_codes_posix.h"
13
14 using blink::WebInputEvent;
15 using blink::WebKeyboardEvent;
16 using blink::WebGestureEvent;
17 using blink::WebMouseEvent;
18 using blink::WebMouseWheelEvent;
19 using blink::WebTouchEvent;
20 using blink::WebTouchPoint;
21
22 namespace content {
23 namespace {
24
25 WebInputEvent::Type ToWebInputEventType(MotionEventAndroid::Action action) {
26   switch (action) {
27     case MotionEventAndroid::ACTION_DOWN:
28       return WebInputEvent::TouchStart;
29     case MotionEventAndroid::ACTION_MOVE:
30       return WebInputEvent::TouchMove;
31     case MotionEventAndroid::ACTION_UP:
32       return WebInputEvent::TouchEnd;
33     case MotionEventAndroid::ACTION_CANCEL:
34       return WebInputEvent::TouchCancel;
35     case MotionEventAndroid::ACTION_POINTER_DOWN:
36       return WebInputEvent::TouchStart;
37     case MotionEventAndroid::ACTION_POINTER_UP:
38       return WebInputEvent::TouchEnd;
39   }
40   NOTREACHED() << "Invalid MotionEventAndroid::Action.";
41   return WebInputEvent::Undefined;
42 }
43
44 // Note that |is_action_pointer| is meaningful only in the context of
45 // |ACTION_POINTER_UP| and |ACTION_POINTER_DOWN|; other actions map directly to
46 // WebTouchPoint::State.
47 WebTouchPoint::State ToWebTouchPointState(MotionEventAndroid::Action action,
48                                           bool is_action_pointer) {
49   switch (action) {
50     case MotionEventAndroid::ACTION_DOWN:
51       return WebTouchPoint::StatePressed;
52     case MotionEventAndroid::ACTION_MOVE:
53       return WebTouchPoint::StateMoved;
54     case MotionEventAndroid::ACTION_UP:
55       return WebTouchPoint::StateReleased;
56     case MotionEventAndroid::ACTION_CANCEL:
57       return WebTouchPoint::StateCancelled;
58     case MotionEventAndroid::ACTION_POINTER_DOWN:
59       return is_action_pointer ? WebTouchPoint::StatePressed
60                                : WebTouchPoint::StateStationary;
61     case MotionEventAndroid::ACTION_POINTER_UP:
62       return is_action_pointer ? WebTouchPoint::StateReleased
63                                : WebTouchPoint::StateStationary;
64   }
65   NOTREACHED() << "Invalid MotionEventAndroid::Action.";
66   return WebTouchPoint::StateUndefined;
67 }
68
69 WebTouchPoint BuildWebTouchPoint(const MotionEventAndroid& event,
70                                  size_t pointer_index,
71                                  float dpi_scale) {
72   WebTouchPoint touch;
73   touch.id = event.GetPointerId(pointer_index);
74   touch.state = ToWebTouchPointState(event.GetActionMasked(),
75                                      pointer_index == event.GetActionIndex());
76   touch.position.x = event.GetX(pointer_index) / dpi_scale;
77   touch.position.y = event.GetY(pointer_index) / dpi_scale;
78   // TODO(joth): Raw event co-ordinates.
79   touch.screenPosition = touch.position;
80
81   const int radius_major =
82       static_cast<int>(event.GetTouchMajor(pointer_index) * 0.5f / dpi_scale);
83   const int radius_minor =
84       static_cast<int>(event.GetTouchMinor(pointer_index) * 0.5f / dpi_scale);
85   const float major_angle_in_radians_clockwise_from_vertical =
86       event.GetOrientation();
87
88   float major_angle_in_degrees_clockwise_from_vertical = 0;
89   if (!std::isnan(major_angle_in_radians_clockwise_from_vertical)) {
90     major_angle_in_degrees_clockwise_from_vertical =
91         major_angle_in_radians_clockwise_from_vertical * 180.f / M_PI;
92   }
93   // Android provides a major axis orientation clockwise with respect to the
94   // vertical of [-90, 90].  The proposed W3C extension specifies the angle that
95   // the ellipse described by radiusX and radiusY is rotated clockwise about
96   // its center, with a value of [0, 90], see
97   // http://www.w3.org/TR/2011/WD-touch-events-20110505/.
98   if (major_angle_in_degrees_clockwise_from_vertical >= 0) {
99     touch.radiusX = radius_minor;
100     touch.radiusY = radius_major;
101     touch.rotationAngle = major_angle_in_degrees_clockwise_from_vertical;
102   } else {
103     touch.radiusX = radius_major;
104     touch.radiusY = radius_minor;
105     touch.rotationAngle = major_angle_in_degrees_clockwise_from_vertical + 90.f;
106   }
107   DCHECK_GE(touch.rotationAngle, 0.f);
108   DCHECK_LE(touch.rotationAngle, 90.f);
109
110   touch.force = event.GetPressure(pointer_index);
111
112   return touch;
113 }
114
115 }  // namespace
116
117 WebKeyboardEvent WebKeyboardEventBuilder::Build(WebInputEvent::Type type,
118                                                 int modifiers,
119                                                 double time_sec,
120                                                 int keycode,
121                                                 int unicode_character,
122                                                 bool is_system_key) {
123   DCHECK(WebInputEvent::isKeyboardEventType(type));
124   WebKeyboardEvent result;
125
126   result.type = type;
127   result.modifiers = modifiers;
128   result.timeStampSeconds = time_sec;
129   ui::KeyboardCode windows_key_code =
130       ui::KeyboardCodeFromAndroidKeyCode(keycode);
131   UpdateWindowsKeyCodeAndKeyIdentifier(&result, windows_key_code);
132   result.modifiers |= GetLocationModifiersFromWindowsKeyCode(windows_key_code);
133   result.nativeKeyCode = keycode;
134   result.unmodifiedText[0] = unicode_character;
135   if (result.windowsKeyCode == ui::VKEY_RETURN) {
136     // This is the same behavior as GTK:
137     // We need to treat the enter key as a key press of character \r. This
138     // is apparently just how webkit handles it and what it expects.
139     result.unmodifiedText[0] = '\r';
140   }
141   result.text[0] = result.unmodifiedText[0];
142   result.isSystemKey = is_system_key;
143
144   return result;
145 }
146
147 WebMouseEvent WebMouseEventBuilder::Build(blink::WebInputEvent::Type type,
148                                           WebMouseEvent::Button button,
149                                           double time_sec,
150                                           int window_x,
151                                           int window_y,
152                                           int modifiers,
153                                           int click_count) {
154   DCHECK(WebInputEvent::isMouseEventType(type));
155   WebMouseEvent result;
156
157   result.type = type;
158   result.x = window_x;
159   result.y = window_y;
160   result.windowX = window_x;
161   result.windowY = window_y;
162   result.timeStampSeconds = time_sec;
163   result.clickCount = click_count;
164   result.modifiers = modifiers;
165
166   if (type == WebInputEvent::MouseDown || type == WebInputEvent::MouseUp)
167     result.button = button;
168   else
169     result.button = WebMouseEvent::ButtonNone;
170
171   return result;
172 }
173
174 WebMouseWheelEvent WebMouseWheelEventBuilder::Build(Direction direction,
175                                                     double time_sec,
176                                                     int window_x,
177                                                     int window_y) {
178   WebMouseWheelEvent result;
179
180   result.type = WebInputEvent::MouseWheel;
181   result.x = window_x;
182   result.y = window_y;
183   result.windowX = window_x;
184   result.windowY = window_y;
185   result.timeStampSeconds = time_sec;
186   result.button = WebMouseEvent::ButtonNone;
187
188   // The below choices are matched from GTK.
189   const float scrollbar_pixels_per_tick = 160.0f / 3.0f;
190
191   switch (direction) {
192     case DIRECTION_UP:
193       result.deltaY = scrollbar_pixels_per_tick;
194       result.wheelTicksY = 1;
195       break;
196     case DIRECTION_DOWN:
197       result.deltaY = -scrollbar_pixels_per_tick;
198       result.wheelTicksY = -1;
199       break;
200     case DIRECTION_LEFT:
201       result.deltaX = scrollbar_pixels_per_tick;
202       result.wheelTicksX = 1;
203       break;
204     case DIRECTION_RIGHT:
205       result.deltaX = -scrollbar_pixels_per_tick;
206       result.wheelTicksX = -1;
207       break;
208   }
209
210   return result;
211 }
212
213 WebGestureEvent WebGestureEventBuilder::Build(WebInputEvent::Type type,
214                                               double time_sec,
215                                               int x,
216                                               int y) {
217   DCHECK(WebInputEvent::isGestureEventType(type));
218   WebGestureEvent result;
219
220   result.type = type;
221   result.x = x;
222   result.y = y;
223   result.timeStampSeconds = time_sec;
224   result.sourceDevice = WebGestureEvent::Touchscreen;
225
226   return result;
227 }
228
229 blink::WebTouchEvent WebTouchEventBuilder::Build(jobject motion_event,
230                                                  float dpi_scale) {
231   DCHECK(motion_event);
232   MotionEventAndroid event(motion_event);
233
234   blink::WebTouchEvent result;
235
236   result.type = ToWebInputEventType(event.GetActionMasked());
237   DCHECK(WebInputEvent::isTouchEventType(result.type));
238
239   result.timeStampSeconds =
240       (event.GetEventTime() - base::TimeTicks()).InSecondsF();
241
242   result.touchesLength =
243       std::min(event.GetPointerCount(),
244                static_cast<size_t>(WebTouchEvent::touchesLengthCap));
245   DCHECK_GT(result.touchesLength, 0U);
246
247   for (size_t i = 0; i < result.touchesLength; ++i)
248     result.touches[i] = BuildWebTouchPoint(event, i, dpi_scale);
249
250   return result;
251 }
252
253 }  // namespace content