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.
5 #include "content/browser/renderer_host/input/motion_event_android.h"
7 #include "base/android/jni_android.h"
8 #include "jni/MotionEvent_jni.h"
10 using base::android::AttachCurrentThread
;
11 using namespace JNI_MotionEvent
;
16 int ToAndroidAction(MotionEventAndroid::Action action
) {
18 case MotionEventAndroid::ACTION_DOWN
:
20 case MotionEventAndroid::ACTION_UP
:
22 case MotionEventAndroid::ACTION_MOVE
:
24 case MotionEventAndroid::ACTION_CANCEL
:
26 case MotionEventAndroid::ACTION_POINTER_DOWN
:
27 return ACTION_POINTER_DOWN
;
28 case MotionEventAndroid::ACTION_POINTER_UP
:
29 return ACTION_POINTER_UP
;
31 NOTREACHED() << "Invalid Android MotionEvent type for gesture detection: "
36 MotionEventAndroid::Action
FromAndroidAction(int android_action
) {
37 switch (android_action
) {
39 return MotionEventAndroid::ACTION_DOWN
;
41 return MotionEventAndroid::ACTION_UP
;
43 return MotionEventAndroid::ACTION_MOVE
;
45 return MotionEventAndroid::ACTION_CANCEL
;
46 case ACTION_POINTER_DOWN
:
47 return MotionEventAndroid::ACTION_POINTER_DOWN
;
48 case ACTION_POINTER_UP
:
49 return MotionEventAndroid::ACTION_POINTER_UP
;
51 NOTREACHED() << "Invalid Android MotionEvent type for gesture detection: "
54 return MotionEventAndroid::ACTION_CANCEL
;
57 int64
ToAndroidTime(base::TimeTicks time
) {
58 return (time
- base::TimeTicks()).InMilliseconds();
61 base::TimeTicks
FromAndroidTime(int64 time_ms
) {
62 return base::TimeTicks() + base::TimeDelta::FromMilliseconds(time_ms
);
67 MotionEventAndroid::MotionEventAndroid(float pix_to_dip
,
75 jfloat pos_x_0_pixels
,
76 jfloat pos_y_0_pixels
,
77 jfloat pos_x_1_pixels
,
78 jfloat pos_y_1_pixels
,
81 jfloat touch_major_0_pixels
,
82 jfloat touch_major_1_pixels
)
83 : cached_time_(FromAndroidTime(time_ms
)),
84 cached_action_(FromAndroidAction(android_action
)),
85 cached_pointer_count_(pointer_count
),
86 cached_history_size_(history_size
),
87 cached_action_index_(action_index
),
88 pix_to_dip_(pix_to_dip
),
89 should_recycle_(false) {
90 DCHECK_GT(pointer_count
, 0);
91 DCHECK_GE(history_size
, 0);
93 event_
.Reset(env
, event
);
96 cached_positions_
[0] = ToDips(gfx::PointF(pos_x_0_pixels
, pos_y_0_pixels
));
97 cached_positions_
[1] = ToDips(gfx::PointF(pos_x_1_pixels
, pos_y_1_pixels
));
98 cached_pointer_ids_
[0] = pointer_id_0
;
99 cached_pointer_ids_
[1] = pointer_id_1
;
100 cached_touch_majors_
[0] = ToDips(touch_major_0_pixels
);
101 cached_touch_majors_
[1] = ToDips(touch_major_1_pixels
);
104 MotionEventAndroid::MotionEventAndroid(float pix_to_dip
,
107 : cached_time_(FromAndroidTime(Java_MotionEvent_getEventTime(env
, event
))),
109 FromAndroidAction(Java_MotionEvent_getActionMasked(env
, event
))),
110 cached_pointer_count_(Java_MotionEvent_getPointerCount(env
, event
)),
111 cached_history_size_(Java_MotionEvent_getHistorySize(env
, event
)),
112 cached_action_index_(Java_MotionEvent_getActionIndex(env
, event
)),
113 pix_to_dip_(pix_to_dip
),
114 should_recycle_(true) {
115 event_
.Reset(env
, event
);
116 DCHECK(event_
.obj());
118 for (size_t i
= 0; i
< MAX_POINTERS_TO_CACHE
; ++i
) {
119 if (i
< cached_pointer_count_
) {
120 cached_positions_
[i
] =
121 ToDips(gfx::PointF(Java_MotionEvent_getXF_I(env
, event
, i
),
122 Java_MotionEvent_getYF_I(env
, event
, i
)));
123 cached_pointer_ids_
[i
] = Java_MotionEvent_getPointerId(env
, event
, i
);
124 cached_touch_majors_
[i
] =
125 ToDips(Java_MotionEvent_getTouchMajorF_I(env
, event
, i
));
127 cached_pointer_ids_
[i
] = 0;
128 cached_touch_majors_
[i
] = 0.f
;
133 MotionEventAndroid::MotionEventAndroid(const MotionEventAndroid
& other
)
134 : event_(Obtain(other
)),
135 cached_time_(other
.cached_time_
),
136 cached_action_(other
.cached_action_
),
137 cached_pointer_count_(other
.cached_pointer_count_
),
138 cached_history_size_(other
.cached_history_size_
),
139 cached_action_index_(other
.cached_action_index_
),
140 pix_to_dip_(other
.pix_to_dip_
),
141 should_recycle_(true) {
142 DCHECK(event_
.obj());
143 for (size_t i
= 0; i
< MAX_POINTERS_TO_CACHE
; ++i
) {
144 cached_positions_
[i
] = other
.cached_positions_
[i
];
145 cached_pointer_ids_
[i
] = other
.cached_pointer_ids_
[i
];
146 cached_touch_majors_
[i
] = other
.cached_touch_majors_
[i
];
150 MotionEventAndroid::~MotionEventAndroid() {
152 Java_MotionEvent_recycle(AttachCurrentThread(), event_
.obj());
155 int MotionEventAndroid::GetId() const {
159 MotionEventAndroid::Action
MotionEventAndroid::GetAction() const {
160 return cached_action_
;
163 int MotionEventAndroid::GetActionIndex() const { return cached_action_index_
; }
165 size_t MotionEventAndroid::GetPointerCount() const {
166 return cached_pointer_count_
;
169 int MotionEventAndroid::GetPointerId(size_t pointer_index
) const {
170 DCHECK_LT(pointer_index
, cached_pointer_count_
);
171 if (pointer_index
< MAX_POINTERS_TO_CACHE
)
172 return cached_pointer_ids_
[pointer_index
];
173 return Java_MotionEvent_getPointerId(
174 AttachCurrentThread(), event_
.obj(), pointer_index
);
177 float MotionEventAndroid::GetX(size_t pointer_index
) const {
178 DCHECK_LT(pointer_index
, cached_pointer_count_
);
179 if (pointer_index
< MAX_POINTERS_TO_CACHE
)
180 return cached_positions_
[pointer_index
].x();
181 return ToDips(Java_MotionEvent_getXF_I(
182 AttachCurrentThread(), event_
.obj(), pointer_index
));
185 float MotionEventAndroid::GetY(size_t pointer_index
) const {
186 DCHECK_LT(pointer_index
, cached_pointer_count_
);
187 if (pointer_index
< MAX_POINTERS_TO_CACHE
)
188 return cached_positions_
[pointer_index
].y();
189 return ToDips(Java_MotionEvent_getYF_I(
190 AttachCurrentThread(), event_
.obj(), pointer_index
));
193 float MotionEventAndroid::GetTouchMajor(size_t pointer_index
) const {
194 DCHECK_LT(pointer_index
, cached_pointer_count_
);
195 if (pointer_index
< MAX_POINTERS_TO_CACHE
)
196 return cached_touch_majors_
[pointer_index
];
197 return ToDips(Java_MotionEvent_getTouchMajorF_I(
198 AttachCurrentThread(), event_
.obj(), pointer_index
));
201 float MotionEventAndroid::GetPressure(size_t pointer_index
) const {
202 DCHECK_LT(pointer_index
, cached_pointer_count_
);
203 return Java_MotionEvent_getPressureF_I(
204 AttachCurrentThread(), event_
.obj(), pointer_index
);
207 base::TimeTicks
MotionEventAndroid::GetEventTime() const {
211 size_t MotionEventAndroid::GetHistorySize() const {
212 return cached_history_size_
;
215 base::TimeTicks
MotionEventAndroid::GetHistoricalEventTime(
216 size_t historical_index
) const {
217 return FromAndroidTime(Java_MotionEvent_getHistoricalEventTime(
218 AttachCurrentThread(), event_
.obj(), historical_index
));
221 float MotionEventAndroid::GetHistoricalTouchMajor(
222 size_t pointer_index
,
223 size_t historical_index
) const {
224 return ToDips(Java_MotionEvent_getHistoricalTouchMajorF_I_I(
225 AttachCurrentThread(), event_
.obj(), pointer_index
, historical_index
));
228 float MotionEventAndroid::GetHistoricalX(size_t pointer_index
,
229 size_t historical_index
) const {
230 return ToDips(Java_MotionEvent_getHistoricalXF_I_I(
231 AttachCurrentThread(), event_
.obj(), pointer_index
, historical_index
));
234 float MotionEventAndroid::GetHistoricalY(size_t pointer_index
,
235 size_t historical_index
) const {
236 return ToDips(Java_MotionEvent_getHistoricalYF_I_I(
237 AttachCurrentThread(), event_
.obj(), pointer_index
, historical_index
));
240 scoped_ptr
<ui::MotionEvent
> MotionEventAndroid::Clone() const {
241 return scoped_ptr
<MotionEvent
>(new MotionEventAndroid(*this));
244 scoped_ptr
<ui::MotionEvent
> MotionEventAndroid::Cancel() const {
245 // The input coordinates to |MotionEventAndroid| are always in device pixels,
246 // but the cached coordinates are in DIPs.
247 const gfx::PointF position_pixels
=
248 gfx::ScalePoint(cached_positions_
[0], 1.f
/ pix_to_dip_
);
249 return scoped_ptr
<MotionEvent
>(
250 new MotionEventAndroid(pix_to_dip_
,
251 AttachCurrentThread(),
252 Obtain(GetDownTime(),
254 MotionEventAndroid::ACTION_CANCEL
,
256 position_pixels
.y()).obj()));
259 float MotionEventAndroid::GetTouchMinor(size_t pointer_index
) const {
260 return ToDips(Java_MotionEvent_getTouchMinorF_I(
261 AttachCurrentThread(), event_
.obj(), pointer_index
));
264 float MotionEventAndroid::GetOrientation() const {
265 return Java_MotionEvent_getOrientationF(AttachCurrentThread(), event_
.obj());
268 base::TimeTicks
MotionEventAndroid::GetDownTime() const {
269 return FromAndroidTime(
270 Java_MotionEvent_getDownTime(AttachCurrentThread(), event_
.obj()));
273 float MotionEventAndroid::ToDips(float pixels
) const {
274 return pixels
* pix_to_dip_
;
277 gfx::PointF
MotionEventAndroid::ToDips(const gfx::PointF
& point_pixels
) const {
278 return gfx::ScalePoint(point_pixels
, pix_to_dip_
);
282 bool MotionEventAndroid::RegisterMotionEventAndroid(JNIEnv
* env
) {
283 return JNI_MotionEvent::RegisterNativesImpl(env
);
287 base::android::ScopedJavaLocalRef
<jobject
> MotionEventAndroid::Obtain(
288 const MotionEventAndroid
& event
) {
289 return Java_MotionEvent_obtainAVME_AVME(AttachCurrentThread(),
294 base::android::ScopedJavaLocalRef
<jobject
> MotionEventAndroid::Obtain(
295 base::TimeTicks down_time
,
296 base::TimeTicks event_time
,
300 return Java_MotionEvent_obtainAVME_J_J_I_F_F_I(AttachCurrentThread(),
301 ToAndroidTime(down_time
),
302 ToAndroidTime(event_time
),
303 ToAndroidAction(action
),
309 } // namespace content