Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / content / browser / renderer_host / input / motion_event_android.cc
1 // Copyright 2014 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/motion_event_android.h"
6
7 #include <android/input.h>
8
9 #include "base/android/jni_android.h"
10 #include "base/float_util.h"
11 #include "jni/MotionEvent_jni.h"
12 #include "ui/events/event_constants.h"
13
14 using base::android::AttachCurrentThread;
15 using namespace JNI_MotionEvent;
16
17 namespace content {
18 namespace {
19
20 MotionEventAndroid::Action FromAndroidAction(int android_action) {
21   switch (android_action) {
22     case ACTION_DOWN:
23       return MotionEventAndroid::ACTION_DOWN;
24     case ACTION_UP:
25       return MotionEventAndroid::ACTION_UP;
26     case ACTION_MOVE:
27       return MotionEventAndroid::ACTION_MOVE;
28     case ACTION_CANCEL:
29       return MotionEventAndroid::ACTION_CANCEL;
30     case ACTION_POINTER_DOWN:
31       return MotionEventAndroid::ACTION_POINTER_DOWN;
32     case ACTION_POINTER_UP:
33       return MotionEventAndroid::ACTION_POINTER_UP;
34     default:
35       NOTREACHED() << "Invalid Android MotionEvent type for gesture detection: "
36                    << android_action;
37   };
38   return MotionEventAndroid::ACTION_CANCEL;
39 }
40
41 MotionEventAndroid::ToolType FromAndroidToolType(int android_tool_type) {
42   switch (android_tool_type) {
43     case TOOL_TYPE_UNKNOWN:
44       return MotionEventAndroid::TOOL_TYPE_UNKNOWN;
45     case TOOL_TYPE_FINGER:
46       return MotionEventAndroid::TOOL_TYPE_FINGER;
47     case TOOL_TYPE_STYLUS:
48       return MotionEventAndroid::TOOL_TYPE_STYLUS;
49     case TOOL_TYPE_MOUSE:
50       return MotionEventAndroid::TOOL_TYPE_MOUSE;
51     case TOOL_TYPE_ERASER:
52       return MotionEventAndroid::TOOL_TYPE_ERASER;
53     default:
54       NOTREACHED() << "Invalid Android MotionEvent tool type: "
55                    << android_tool_type;
56   };
57   return MotionEventAndroid::TOOL_TYPE_UNKNOWN;
58 }
59
60 int FromAndroidButtonState(int button_state) {
61   int result = 0;
62   if ((button_state & BUTTON_BACK) != 0)
63     result |= MotionEventAndroid::BUTTON_BACK;
64   if ((button_state & BUTTON_FORWARD) != 0)
65     result |= MotionEventAndroid::BUTTON_FORWARD;
66   if ((button_state & BUTTON_PRIMARY) != 0)
67     result |= MotionEventAndroid::BUTTON_PRIMARY;
68   if ((button_state & BUTTON_SECONDARY) != 0)
69     result |= MotionEventAndroid::BUTTON_SECONDARY;
70   if ((button_state & BUTTON_TERTIARY) != 0)
71     result |= MotionEventAndroid::BUTTON_TERTIARY;
72   return result;
73 }
74
75 int FromAndroidMetaState(int meta_state) {
76   int flags = ui::EF_NONE;
77   if ((meta_state & AMETA_SHIFT_ON) != 0)
78     flags |= ui::EF_SHIFT_DOWN;
79   if ((meta_state & AMETA_CTRL_ON) != 0)
80     flags |= ui::EF_CONTROL_DOWN;
81   if ((meta_state & AMETA_ALT_ON) != 0)
82     flags |= ui::EF_ALT_DOWN;
83   if ((meta_state & AMETA_META_ON) != 0)
84     flags |= ui::EF_COMMAND_DOWN;
85   if ((meta_state & AMETA_CAPS_LOCK_ON) != 0)
86     flags |= ui::EF_CAPS_LOCK_DOWN;
87   return flags;
88 }
89
90 base::TimeTicks FromAndroidTime(int64 time_ms) {
91   return base::TimeTicks() + base::TimeDelta::FromMilliseconds(time_ms);
92 }
93
94 float ToValidFloat(float x) {
95   if (base::IsNaN(x))
96     return 0.f;
97
98   // Wildly large orientation values have been observed in the wild after device
99   // rotation. There's not much we can do in that case other than simply
100   // sanitize results beyond an absurd and arbitrary threshold.
101   if (std::abs(x) > 1e5f)
102     return 0.f;
103
104   return x;
105 }
106
107 }  // namespace
108
109 MotionEventAndroid::Pointer::Pointer(jint id,
110                                      jfloat pos_x_pixels,
111                                      jfloat pos_y_pixels,
112                                      jfloat touch_major_pixels,
113                                      jfloat touch_minor_pixels,
114                                      jfloat orientation_rad,
115                                      jint tool_type)
116     : id(id),
117       pos_x_pixels(pos_x_pixels),
118       pos_y_pixels(pos_y_pixels),
119       touch_major_pixels(touch_major_pixels),
120       touch_minor_pixels(touch_minor_pixels),
121       orientation_rad(orientation_rad),
122       tool_type(tool_type) {
123 }
124
125 MotionEventAndroid::CachedPointer::CachedPointer()
126     : id(0),
127       touch_major(0),
128       touch_minor(0),
129       orientation(0),
130       tool_type(TOOL_TYPE_UNKNOWN) {
131 }
132
133 MotionEventAndroid::MotionEventAndroid(float pix_to_dip,
134                                        JNIEnv* env,
135                                        jobject event,
136                                        jlong time_ms,
137                                        jint android_action,
138                                        jint pointer_count,
139                                        jint history_size,
140                                        jint action_index,
141                                        jint android_button_state,
142                                        jint meta_state,
143                                        jfloat raw_offset_x_pixels,
144                                        jfloat raw_offset_y_pixels,
145                                        const Pointer& pointer0,
146                                        const Pointer& pointer1)
147     : pix_to_dip_(pix_to_dip),
148       cached_time_(FromAndroidTime(time_ms)),
149       cached_action_(FromAndroidAction(android_action)),
150       cached_pointer_count_(pointer_count),
151       cached_history_size_(history_size),
152       cached_action_index_(action_index),
153       cached_button_state_(FromAndroidButtonState(android_button_state)),
154       cached_flags_(FromAndroidMetaState(meta_state)),
155       cached_raw_position_offset_(ToDips(raw_offset_x_pixels),
156                                   ToDips(raw_offset_y_pixels)) {
157   DCHECK_GT(pointer_count, 0);
158   DCHECK_GE(history_size, 0);
159
160   event_.Reset(env, event);
161   if (cached_pointer_count_ > MAX_POINTERS_TO_CACHE || history_size > 0)
162     DCHECK(event_.obj());
163
164   cached_pointers_[0] = FromAndroidPointer(pointer0);
165   cached_pointers_[1] = FromAndroidPointer(pointer1);
166 }
167
168 MotionEventAndroid::~MotionEventAndroid() {
169 }
170
171 int MotionEventAndroid::GetId() const {
172   return 0;
173 }
174
175 MotionEventAndroid::Action MotionEventAndroid::GetAction() const {
176   return cached_action_;
177 }
178
179 int MotionEventAndroid::GetActionIndex() const {
180   return cached_action_index_;
181 }
182
183 size_t MotionEventAndroid::GetPointerCount() const {
184   return cached_pointer_count_;
185 }
186
187 int MotionEventAndroid::GetPointerId(size_t pointer_index) const {
188   DCHECK_LT(pointer_index, cached_pointer_count_);
189   if (pointer_index < MAX_POINTERS_TO_CACHE)
190     return cached_pointers_[pointer_index].id;
191   return Java_MotionEvent_getPointerId(
192       AttachCurrentThread(), event_.obj(), pointer_index);
193 }
194
195 float MotionEventAndroid::GetX(size_t pointer_index) const {
196   DCHECK_LT(pointer_index, cached_pointer_count_);
197   if (pointer_index < MAX_POINTERS_TO_CACHE)
198     return cached_pointers_[pointer_index].position.x();
199   return ToDips(Java_MotionEvent_getXF_I(
200       AttachCurrentThread(), event_.obj(), pointer_index));
201 }
202
203 float MotionEventAndroid::GetY(size_t pointer_index) const {
204   DCHECK_LT(pointer_index, cached_pointer_count_);
205   if (pointer_index < MAX_POINTERS_TO_CACHE)
206     return cached_pointers_[pointer_index].position.y();
207   return ToDips(Java_MotionEvent_getYF_I(
208       AttachCurrentThread(), event_.obj(), pointer_index));
209 }
210
211 float MotionEventAndroid::GetRawX(size_t pointer_index) const {
212   return GetX(pointer_index) + cached_raw_position_offset_.x();
213 }
214
215 float MotionEventAndroid::GetRawY(size_t pointer_index) const {
216   return GetY(pointer_index) + cached_raw_position_offset_.y();
217 }
218
219 float MotionEventAndroid::GetTouchMajor(size_t pointer_index) const {
220   DCHECK_LT(pointer_index, cached_pointer_count_);
221   if (pointer_index < MAX_POINTERS_TO_CACHE)
222     return cached_pointers_[pointer_index].touch_major;
223   return ToDips(Java_MotionEvent_getTouchMajorF_I(
224       AttachCurrentThread(), event_.obj(), pointer_index));
225 }
226
227 float MotionEventAndroid::GetTouchMinor(size_t pointer_index) const {
228   DCHECK_LT(pointer_index, cached_pointer_count_);
229   if (pointer_index < MAX_POINTERS_TO_CACHE)
230     return cached_pointers_[pointer_index].touch_minor;
231   return ToDips(Java_MotionEvent_getTouchMinorF_I(
232       AttachCurrentThread(), event_.obj(), pointer_index));
233 }
234
235 float MotionEventAndroid::GetOrientation(size_t pointer_index) const {
236   DCHECK_LT(pointer_index, cached_pointer_count_);
237   if (pointer_index < MAX_POINTERS_TO_CACHE)
238     return cached_pointers_[pointer_index].orientation;
239   return ToValidFloat(Java_MotionEvent_getOrientationF_I(
240       AttachCurrentThread(), event_.obj(), pointer_index));
241 }
242
243 float MotionEventAndroid::GetPressure(size_t pointer_index) const {
244   DCHECK_LT(pointer_index, cached_pointer_count_);
245   // Note that this early return is a special case exercised only in testing, as
246   // caching the pressure values is not a worthwhile optimization (they're
247   // accessed at most once per event instance).
248   if (!event_.obj())
249     return 0.f;
250   return Java_MotionEvent_getPressureF_I(
251       AttachCurrentThread(), event_.obj(), pointer_index);
252 }
253
254 base::TimeTicks MotionEventAndroid::GetEventTime() const {
255   return cached_time_;
256 }
257
258 size_t MotionEventAndroid::GetHistorySize() const {
259   return cached_history_size_;
260 }
261
262 base::TimeTicks MotionEventAndroid::GetHistoricalEventTime(
263     size_t historical_index) const {
264   return FromAndroidTime(Java_MotionEvent_getHistoricalEventTime(
265       AttachCurrentThread(), event_.obj(), historical_index));
266 }
267
268 float MotionEventAndroid::GetHistoricalTouchMajor(
269     size_t pointer_index,
270     size_t historical_index) const {
271   return ToDips(Java_MotionEvent_getHistoricalTouchMajorF_I_I(
272       AttachCurrentThread(), event_.obj(), pointer_index, historical_index));
273 }
274
275 float MotionEventAndroid::GetHistoricalX(size_t pointer_index,
276                                          size_t historical_index) const {
277   return ToDips(Java_MotionEvent_getHistoricalXF_I_I(
278       AttachCurrentThread(), event_.obj(), pointer_index, historical_index));
279 }
280
281 float MotionEventAndroid::GetHistoricalY(size_t pointer_index,
282                                          size_t historical_index) const {
283   return ToDips(Java_MotionEvent_getHistoricalYF_I_I(
284       AttachCurrentThread(), event_.obj(), pointer_index, historical_index));
285 }
286
287 ui::MotionEvent::ToolType MotionEventAndroid::GetToolType(
288     size_t pointer_index) const {
289   DCHECK_LT(pointer_index, cached_pointer_count_);
290   if (pointer_index < MAX_POINTERS_TO_CACHE)
291     return cached_pointers_[pointer_index].tool_type;
292   return FromAndroidToolType(Java_MotionEvent_getToolType(
293       AttachCurrentThread(), event_.obj(), pointer_index));
294 }
295
296 int MotionEventAndroid::GetButtonState() const {
297   return cached_button_state_;
298 }
299
300 int MotionEventAndroid::GetFlags() const {
301   return cached_flags_;
302 }
303
304 float MotionEventAndroid::ToDips(float pixels) const {
305   return pixels * pix_to_dip_;
306 }
307
308 MotionEventAndroid::CachedPointer MotionEventAndroid::FromAndroidPointer(
309     const Pointer& pointer) const {
310   CachedPointer result;
311   result.id = pointer.id;
312   result.position =
313       gfx::PointF(ToDips(pointer.pos_x_pixels), ToDips(pointer.pos_y_pixels));
314   result.touch_major = ToDips(pointer.touch_major_pixels);
315   result.touch_minor = ToDips(pointer.touch_minor_pixels);
316   result.orientation = ToValidFloat(pointer.orientation_rad);
317   result.tool_type = FromAndroidToolType(pointer.tool_type);
318   return result;
319 }
320
321 // static
322 bool MotionEventAndroid::RegisterMotionEventAndroid(JNIEnv* env) {
323   return JNI_MotionEvent::RegisterNativesImpl(env);
324 }
325
326 }  // namespace content