2 * Copyright (C) 2010 The Android Open Source Project
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 #define LOG_TAG "MotionEvent-JNI"
22 #include <android_runtime/AndroidRuntime.h>
23 #include <android_runtime/Log.h>
24 #include <utils/Log.h>
25 #include <input/Input.h>
26 #include "android_os_Parcel.h"
27 #include "android_view_MotionEvent.h"
28 #include "android_util_Binder.h"
29 #include "android/graphics/Matrix.h"
33 // ----------------------------------------------------------------------------
42 } gMotionEventClassInfo;
45 jfieldID mPackedAxisBits;
46 jfieldID mPackedAxisValues;
56 } gPointerCoordsClassInfo;
61 } gPointerPropertiesClassInfo;
63 // ----------------------------------------------------------------------------
65 MotionEvent* android_view_MotionEvent_getNativePtr(JNIEnv* env, jobject eventObj) {
69 return reinterpret_cast<MotionEvent*>(
70 env->GetIntField(eventObj, gMotionEventClassInfo.mNativePtr));
73 static void android_view_MotionEvent_setNativePtr(JNIEnv* env, jobject eventObj,
75 env->SetIntField(eventObj, gMotionEventClassInfo.mNativePtr,
76 reinterpret_cast<int>(event));
79 jobject android_view_MotionEvent_obtainAsCopy(JNIEnv* env, const MotionEvent* event) {
80 jobject eventObj = env->CallStaticObjectMethod(gMotionEventClassInfo.clazz,
81 gMotionEventClassInfo.obtain);
82 if (env->ExceptionCheck() || !eventObj) {
83 ALOGE("An exception occurred while obtaining a motion event.");
85 env->ExceptionClear();
89 MotionEvent* destEvent = android_view_MotionEvent_getNativePtr(env, eventObj);
91 destEvent = new MotionEvent();
92 android_view_MotionEvent_setNativePtr(env, eventObj, destEvent);
95 destEvent->copyFrom(event, true);
99 status_t android_view_MotionEvent_recycle(JNIEnv* env, jobject eventObj) {
100 env->CallVoidMethod(eventObj, gMotionEventClassInfo.recycle);
101 if (env->ExceptionCheck()) {
102 ALOGW("An exception occurred while recycling a motion event.");
104 env->ExceptionClear();
105 return UNKNOWN_ERROR;
110 // ----------------------------------------------------------------------------
112 static const jint HISTORY_CURRENT = -0x80000000;
114 static bool validatePointerCount(JNIEnv* env, jint pointerCount) {
115 if (pointerCount < 1) {
116 jniThrowException(env, "java/lang/IllegalArgumentException",
117 "pointerCount must be at least 1");
123 static bool validatePointerPropertiesArray(JNIEnv* env, jobjectArray pointerPropertiesObjArray,
124 size_t pointerCount) {
125 if (!pointerPropertiesObjArray) {
126 jniThrowException(env, "java/lang/IllegalArgumentException",
127 "pointerProperties array must not be null");
130 size_t length = size_t(env->GetArrayLength(pointerPropertiesObjArray));
131 if (length < pointerCount) {
132 jniThrowException(env, "java/lang/IllegalArgumentException",
133 "pointerProperties array must be large enough to hold all pointers");
139 static bool validatePointerCoordsObjArray(JNIEnv* env, jobjectArray pointerCoordsObjArray,
140 size_t pointerCount) {
141 if (!pointerCoordsObjArray) {
142 jniThrowException(env, "java/lang/IllegalArgumentException",
143 "pointerCoords array must not be null");
146 size_t length = size_t(env->GetArrayLength(pointerCoordsObjArray));
147 if (length < pointerCount) {
148 jniThrowException(env, "java/lang/IllegalArgumentException",
149 "pointerCoords array must be large enough to hold all pointers");
155 static bool validatePointerIndex(JNIEnv* env, jint pointerIndex, size_t pointerCount) {
156 if (pointerIndex < 0 || size_t(pointerIndex) >= pointerCount) {
157 jniThrowException(env, "java/lang/IllegalArgumentException",
158 "pointerIndex out of range");
164 static bool validateHistoryPos(JNIEnv* env, jint historyPos, size_t historySize) {
165 if (historyPos < 0 || size_t(historyPos) >= historySize) {
166 jniThrowException(env, "java/lang/IllegalArgumentException",
167 "historyPos out of range");
173 static bool validatePointerCoords(JNIEnv* env, jobject pointerCoordsObj) {
174 if (!pointerCoordsObj) {
175 jniThrowException(env, "java/lang/IllegalArgumentException",
176 "pointerCoords must not be null");
182 static bool validatePointerProperties(JNIEnv* env, jobject pointerPropertiesObj) {
183 if (!pointerPropertiesObj) {
184 jniThrowException(env, "java/lang/IllegalArgumentException",
185 "pointerProperties must not be null");
191 static void pointerCoordsToNative(JNIEnv* env, jobject pointerCoordsObj,
192 float xOffset, float yOffset, PointerCoords* outRawPointerCoords) {
193 outRawPointerCoords->clear();
194 outRawPointerCoords->setAxisValue(AMOTION_EVENT_AXIS_X,
195 env->GetFloatField(pointerCoordsObj, gPointerCoordsClassInfo.x) - xOffset);
196 outRawPointerCoords->setAxisValue(AMOTION_EVENT_AXIS_Y,
197 env->GetFloatField(pointerCoordsObj, gPointerCoordsClassInfo.y) - yOffset);
198 outRawPointerCoords->setAxisValue(AMOTION_EVENT_AXIS_PRESSURE,
199 env->GetFloatField(pointerCoordsObj, gPointerCoordsClassInfo.pressure));
200 outRawPointerCoords->setAxisValue(AMOTION_EVENT_AXIS_SIZE,
201 env->GetFloatField(pointerCoordsObj, gPointerCoordsClassInfo.size));
202 outRawPointerCoords->setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR,
203 env->GetFloatField(pointerCoordsObj, gPointerCoordsClassInfo.touchMajor));
204 outRawPointerCoords->setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR,
205 env->GetFloatField(pointerCoordsObj, gPointerCoordsClassInfo.touchMinor));
206 outRawPointerCoords->setAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR,
207 env->GetFloatField(pointerCoordsObj, gPointerCoordsClassInfo.toolMajor));
208 outRawPointerCoords->setAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR,
209 env->GetFloatField(pointerCoordsObj, gPointerCoordsClassInfo.toolMinor));
210 outRawPointerCoords->setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION,
211 env->GetFloatField(pointerCoordsObj, gPointerCoordsClassInfo.orientation));
213 uint64_t bits = env->GetLongField(pointerCoordsObj, gPointerCoordsClassInfo.mPackedAxisBits);
215 jfloatArray valuesArray = jfloatArray(env->GetObjectField(pointerCoordsObj,
216 gPointerCoordsClassInfo.mPackedAxisValues));
218 jfloat* values = static_cast<jfloat*>(
219 env->GetPrimitiveArrayCritical(valuesArray, NULL));
223 uint32_t axis = __builtin_ctzll(bits);
224 uint64_t axisBit = 1LL << axis;
226 outRawPointerCoords->setAxisValue(axis, values[index++]);
229 env->ReleasePrimitiveArrayCritical(valuesArray, values, JNI_ABORT);
230 env->DeleteLocalRef(valuesArray);
235 static jfloatArray obtainPackedAxisValuesArray(JNIEnv* env, uint32_t minSize,
236 jobject outPointerCoordsObj) {
237 jfloatArray outValuesArray = jfloatArray(env->GetObjectField(outPointerCoordsObj,
238 gPointerCoordsClassInfo.mPackedAxisValues));
239 if (outValuesArray) {
240 uint32_t size = env->GetArrayLength(outValuesArray);
241 if (minSize <= size) {
242 return outValuesArray;
244 env->DeleteLocalRef(outValuesArray);
247 while (size < minSize) {
250 outValuesArray = env->NewFloatArray(size);
251 env->SetObjectField(outPointerCoordsObj,
252 gPointerCoordsClassInfo.mPackedAxisValues, outValuesArray);
253 return outValuesArray;
256 static void pointerCoordsFromNative(JNIEnv* env, const PointerCoords* rawPointerCoords,
257 float xOffset, float yOffset, jobject outPointerCoordsObj) {
258 env->SetFloatField(outPointerCoordsObj, gPointerCoordsClassInfo.x,
259 rawPointerCoords->getAxisValue(AMOTION_EVENT_AXIS_X) + xOffset);
260 env->SetFloatField(outPointerCoordsObj, gPointerCoordsClassInfo.y,
261 rawPointerCoords->getAxisValue(AMOTION_EVENT_AXIS_Y) + yOffset);
262 env->SetFloatField(outPointerCoordsObj, gPointerCoordsClassInfo.pressure,
263 rawPointerCoords->getAxisValue(AMOTION_EVENT_AXIS_PRESSURE));
264 env->SetFloatField(outPointerCoordsObj, gPointerCoordsClassInfo.size,
265 rawPointerCoords->getAxisValue(AMOTION_EVENT_AXIS_SIZE));
266 env->SetFloatField(outPointerCoordsObj, gPointerCoordsClassInfo.touchMajor,
267 rawPointerCoords->getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR));
268 env->SetFloatField(outPointerCoordsObj, gPointerCoordsClassInfo.touchMinor,
269 rawPointerCoords->getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR));
270 env->SetFloatField(outPointerCoordsObj, gPointerCoordsClassInfo.toolMajor,
271 rawPointerCoords->getAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR));
272 env->SetFloatField(outPointerCoordsObj, gPointerCoordsClassInfo.toolMinor,
273 rawPointerCoords->getAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR));
274 env->SetFloatField(outPointerCoordsObj, gPointerCoordsClassInfo.orientation,
275 rawPointerCoords->getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION));
277 const uint64_t unpackedAxisBits = 0
278 | (1LL << AMOTION_EVENT_AXIS_X)
279 | (1LL << AMOTION_EVENT_AXIS_Y)
280 | (1LL << AMOTION_EVENT_AXIS_PRESSURE)
281 | (1LL << AMOTION_EVENT_AXIS_SIZE)
282 | (1LL << AMOTION_EVENT_AXIS_TOUCH_MAJOR)
283 | (1LL << AMOTION_EVENT_AXIS_TOUCH_MINOR)
284 | (1LL << AMOTION_EVENT_AXIS_TOOL_MAJOR)
285 | (1LL << AMOTION_EVENT_AXIS_TOOL_MINOR)
286 | (1LL << AMOTION_EVENT_AXIS_ORIENTATION);
288 uint64_t outBits = 0;
289 uint64_t remainingBits = rawPointerCoords->bits & ~unpackedAxisBits;
291 uint32_t packedAxesCount = __builtin_popcountll(remainingBits);
292 jfloatArray outValuesArray = obtainPackedAxisValuesArray(env, packedAxesCount,
293 outPointerCoordsObj);
294 if (!outValuesArray) {
298 jfloat* outValues = static_cast<jfloat*>(env->GetPrimitiveArrayCritical(
299 outValuesArray, NULL));
301 const float* values = rawPointerCoords->values;
304 uint32_t axis = __builtin_ctzll(remainingBits);
305 uint64_t axisBit = 1LL << axis;
306 remainingBits &= ~axisBit;
308 outValues[index++] = rawPointerCoords->getAxisValue(axis);
309 } while (remainingBits);
311 env->ReleasePrimitiveArrayCritical(outValuesArray, outValues, 0);
312 env->DeleteLocalRef(outValuesArray);
314 env->SetLongField(outPointerCoordsObj, gPointerCoordsClassInfo.mPackedAxisBits, outBits);
317 static void pointerPropertiesToNative(JNIEnv* env, jobject pointerPropertiesObj,
318 PointerProperties* outPointerProperties) {
319 outPointerProperties->clear();
320 outPointerProperties->id = env->GetIntField(pointerPropertiesObj,
321 gPointerPropertiesClassInfo.id);
322 outPointerProperties->toolType = env->GetIntField(pointerPropertiesObj,
323 gPointerPropertiesClassInfo.toolType);
326 static void pointerPropertiesFromNative(JNIEnv* env, const PointerProperties* pointerProperties,
327 jobject outPointerPropertiesObj) {
328 env->SetIntField(outPointerPropertiesObj, gPointerPropertiesClassInfo.id,
329 pointerProperties->id);
330 env->SetIntField(outPointerPropertiesObj, gPointerPropertiesClassInfo.toolType,
331 pointerProperties->toolType);
335 // ----------------------------------------------------------------------------
337 static jint android_view_MotionEvent_nativeInitialize(JNIEnv* env, jclass clazz,
339 jint deviceId, jint source, jint action, jint flags, jint edgeFlags,
340 jint metaState, jint buttonState,
341 jfloat xOffset, jfloat yOffset, jfloat xPrecision, jfloat yPrecision,
342 jlong downTimeNanos, jlong eventTimeNanos,
343 jint pointerCount, jobjectArray pointerPropertiesObjArray,
344 jobjectArray pointerCoordsObjArray) {
345 if (!validatePointerCount(env, pointerCount)
346 || !validatePointerPropertiesArray(env, pointerPropertiesObjArray, pointerCount)
347 || !validatePointerCoordsObjArray(env, pointerCoordsObjArray, pointerCount)) {
351 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
353 event = new MotionEvent();
356 PointerProperties pointerProperties[pointerCount];
357 PointerCoords rawPointerCoords[pointerCount];
359 for (jint i = 0; i < pointerCount; i++) {
360 jobject pointerPropertiesObj = env->GetObjectArrayElement(pointerPropertiesObjArray, i);
361 if (!pointerPropertiesObj) {
364 pointerPropertiesToNative(env, pointerPropertiesObj, &pointerProperties[i]);
365 env->DeleteLocalRef(pointerPropertiesObj);
367 jobject pointerCoordsObj = env->GetObjectArrayElement(pointerCoordsObjArray, i);
368 if (!pointerCoordsObj) {
369 jniThrowNullPointerException(env, "pointerCoords");
372 pointerCoordsToNative(env, pointerCoordsObj, xOffset, yOffset, &rawPointerCoords[i]);
373 env->DeleteLocalRef(pointerCoordsObj);
376 event->initialize(deviceId, source, action, flags, edgeFlags, metaState, buttonState,
377 xOffset, yOffset, xPrecision, yPrecision,
378 downTimeNanos, eventTimeNanos, pointerCount, pointerProperties, rawPointerCoords);
380 return reinterpret_cast<jint>(event);
389 static jint android_view_MotionEvent_nativeCopy(JNIEnv* env, jclass clazz,
390 jint destNativePtr, jint sourceNativePtr, jboolean keepHistory) {
391 MotionEvent* destEvent = reinterpret_cast<MotionEvent*>(destNativePtr);
393 destEvent = new MotionEvent();
395 MotionEvent* sourceEvent = reinterpret_cast<MotionEvent*>(sourceNativePtr);
396 destEvent->copyFrom(sourceEvent, keepHistory);
397 return reinterpret_cast<jint>(destEvent);
400 static void android_view_MotionEvent_nativeDispose(JNIEnv* env, jclass clazz,
402 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
406 static void android_view_MotionEvent_nativeAddBatch(JNIEnv* env, jclass clazz,
407 jint nativePtr, jlong eventTimeNanos, jobjectArray pointerCoordsObjArray,
409 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
410 size_t pointerCount = event->getPointerCount();
411 if (!validatePointerCoordsObjArray(env, pointerCoordsObjArray, pointerCount)) {
415 PointerCoords rawPointerCoords[pointerCount];
417 for (size_t i = 0; i < pointerCount; i++) {
418 jobject pointerCoordsObj = env->GetObjectArrayElement(pointerCoordsObjArray, i);
419 if (!pointerCoordsObj) {
420 jniThrowNullPointerException(env, "pointerCoords");
423 pointerCoordsToNative(env, pointerCoordsObj,
424 event->getXOffset(), event->getYOffset(), &rawPointerCoords[i]);
425 env->DeleteLocalRef(pointerCoordsObj);
428 event->addSample(eventTimeNanos, rawPointerCoords);
429 event->setMetaState(event->getMetaState() | metaState);
432 static jint android_view_MotionEvent_nativeGetDeviceId(JNIEnv* env, jclass clazz,
434 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
435 return event->getDeviceId();
438 static jint android_view_MotionEvent_nativeGetSource(JNIEnv* env, jclass clazz,
440 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
441 return event->getSource();
444 static void android_view_MotionEvent_nativeSetSource(JNIEnv* env, jclass clazz,
445 jint nativePtr, jint source) {
446 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
447 event->setSource(source);
450 static jint android_view_MotionEvent_nativeGetAction(JNIEnv* env, jclass clazz,
452 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
453 return event->getAction();
456 static void android_view_MotionEvent_nativeSetAction(JNIEnv* env, jclass clazz,
457 jint nativePtr, jint action) {
458 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
459 event->setAction(action);
462 static jboolean android_view_MotionEvent_nativeIsTouchEvent(JNIEnv* env, jclass clazz,
464 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
465 return event->isTouchEvent();
468 static jint android_view_MotionEvent_nativeGetFlags(JNIEnv* env, jclass clazz,
470 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
471 return event->getFlags();
474 static void android_view_MotionEvent_nativeSetFlags(JNIEnv* env, jclass clazz,
475 jint nativePtr, jint flags) {
476 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
477 event->setFlags(flags);
480 static jint android_view_MotionEvent_nativeGetEdgeFlags(JNIEnv* env, jclass clazz,
482 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
483 return event->getEdgeFlags();
486 static void android_view_MotionEvent_nativeSetEdgeFlags(JNIEnv* env, jclass clazz,
487 jint nativePtr, jint edgeFlags) {
488 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
489 event->setEdgeFlags(edgeFlags);
492 static jint android_view_MotionEvent_nativeGetMetaState(JNIEnv* env, jclass clazz,
494 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
495 return event->getMetaState();
498 static jint android_view_MotionEvent_nativeGetButtonState(JNIEnv* env, jclass clazz,
500 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
501 return event->getButtonState();
504 static void android_view_MotionEvent_nativeOffsetLocation(JNIEnv* env, jclass clazz,
505 jint nativePtr, jfloat deltaX, jfloat deltaY) {
506 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
507 return event->offsetLocation(deltaX, deltaY);
510 static jfloat android_view_MotionEvent_nativeGetXOffset(JNIEnv* env, jclass clazz,
512 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
513 return event->getXOffset();
516 static jfloat android_view_MotionEvent_nativeGetYOffset(JNIEnv* env, jclass clazz,
518 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
519 return event->getYOffset();
522 static jfloat android_view_MotionEvent_nativeGetXPrecision(JNIEnv* env, jclass clazz,
524 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
525 return event->getXPrecision();
528 static jfloat android_view_MotionEvent_nativeGetYPrecision(JNIEnv* env, jclass clazz,
530 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
531 return event->getYPrecision();
534 static jlong android_view_MotionEvent_nativeGetDownTimeNanos(JNIEnv* env, jclass clazz,
536 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
537 return event->getDownTime();
540 static void android_view_MotionEvent_nativeSetDownTimeNanos(JNIEnv* env, jclass clazz,
541 jint nativePtr, jlong downTimeNanos) {
542 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
543 event->setDownTime(downTimeNanos);
546 static jint android_view_MotionEvent_nativeGetPointerCount(JNIEnv* env, jclass clazz,
548 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
549 return jint(event->getPointerCount());
552 static jint android_view_MotionEvent_nativeGetPointerId(JNIEnv* env, jclass clazz,
553 jint nativePtr, jint pointerIndex) {
554 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
555 size_t pointerCount = event->getPointerCount();
556 if (!validatePointerIndex(env, pointerIndex, pointerCount)) {
559 return event->getPointerId(pointerIndex);
562 static jint android_view_MotionEvent_nativeGetToolType(JNIEnv* env, jclass clazz,
563 jint nativePtr, jint pointerIndex) {
564 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
565 size_t pointerCount = event->getPointerCount();
566 if (!validatePointerIndex(env, pointerIndex, pointerCount)) {
569 return event->getToolType(pointerIndex);
572 static jint android_view_MotionEvent_nativeFindPointerIndex(JNIEnv* env, jclass clazz,
573 jint nativePtr, jint pointerId) {
574 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
575 return jint(event->findPointerIndex(pointerId));
578 static jint android_view_MotionEvent_nativeGetHistorySize(JNIEnv* env, jclass clazz,
580 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
581 return jint(event->getHistorySize());
584 static jlong android_view_MotionEvent_nativeGetEventTimeNanos(JNIEnv* env, jclass clazz,
585 jint nativePtr, jint historyPos) {
586 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
587 if (historyPos == HISTORY_CURRENT) {
588 return event->getEventTime();
590 size_t historySize = event->getHistorySize();
591 if (!validateHistoryPos(env, historyPos, historySize)) {
594 return event->getHistoricalEventTime(historyPos);
598 static jfloat android_view_MotionEvent_nativeGetRawAxisValue(JNIEnv* env, jclass clazz,
599 jint nativePtr, jint axis, jint pointerIndex, jint historyPos) {
600 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
601 size_t pointerCount = event->getPointerCount();
602 if (!validatePointerIndex(env, pointerIndex, pointerCount)) {
606 if (historyPos == HISTORY_CURRENT) {
607 return event->getRawAxisValue(axis, pointerIndex);
609 size_t historySize = event->getHistorySize();
610 if (!validateHistoryPos(env, historyPos, historySize)) {
613 return event->getHistoricalRawAxisValue(axis, pointerIndex, historyPos);
617 static jfloat android_view_MotionEvent_nativeGetAxisValue(JNIEnv* env, jclass clazz,
618 jint nativePtr, jint axis, jint pointerIndex, jint historyPos) {
619 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
620 size_t pointerCount = event->getPointerCount();
621 if (!validatePointerIndex(env, pointerIndex, pointerCount)) {
625 if (historyPos == HISTORY_CURRENT) {
626 return event->getAxisValue(axis, pointerIndex);
628 size_t historySize = event->getHistorySize();
629 if (!validateHistoryPos(env, historyPos, historySize)) {
632 return event->getHistoricalAxisValue(axis, pointerIndex, historyPos);
636 static void android_view_MotionEvent_nativeGetPointerCoords(JNIEnv* env, jclass clazz,
637 jint nativePtr, jint pointerIndex, jint historyPos, jobject outPointerCoordsObj) {
638 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
639 size_t pointerCount = event->getPointerCount();
640 if (!validatePointerIndex(env, pointerIndex, pointerCount)
641 || !validatePointerCoords(env, outPointerCoordsObj)) {
645 const PointerCoords* rawPointerCoords;
646 if (historyPos == HISTORY_CURRENT) {
647 rawPointerCoords = event->getRawPointerCoords(pointerIndex);
649 size_t historySize = event->getHistorySize();
650 if (!validateHistoryPos(env, historyPos, historySize)) {
653 rawPointerCoords = event->getHistoricalRawPointerCoords(pointerIndex, historyPos);
655 pointerCoordsFromNative(env, rawPointerCoords, event->getXOffset(), event->getYOffset(),
656 outPointerCoordsObj);
659 static void android_view_MotionEvent_nativeGetPointerProperties(JNIEnv* env, jclass clazz,
660 jint nativePtr, jint pointerIndex, jobject outPointerPropertiesObj) {
661 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
662 size_t pointerCount = event->getPointerCount();
663 if (!validatePointerIndex(env, pointerIndex, pointerCount)
664 || !validatePointerProperties(env, outPointerPropertiesObj)) {
668 const PointerProperties* pointerProperties = event->getPointerProperties(pointerIndex);
669 pointerPropertiesFromNative(env, pointerProperties, outPointerPropertiesObj);
672 static void android_view_MotionEvent_nativeScale(JNIEnv* env, jclass clazz,
673 jint nativePtr, jfloat scale) {
674 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
678 static void android_view_MotionEvent_nativeTransform(JNIEnv* env, jclass clazz,
679 jint nativePtr, jobject matrixObj) {
680 SkMatrix* matrix = android_graphics_Matrix_getSkMatrix(env, matrixObj);
681 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
684 m[0] = SkScalarToFloat(matrix->get(SkMatrix::kMScaleX));
685 m[1] = SkScalarToFloat(matrix->get(SkMatrix::kMSkewX));
686 m[2] = SkScalarToFloat(matrix->get(SkMatrix::kMTransX));
687 m[3] = SkScalarToFloat(matrix->get(SkMatrix::kMSkewY));
688 m[4] = SkScalarToFloat(matrix->get(SkMatrix::kMScaleY));
689 m[5] = SkScalarToFloat(matrix->get(SkMatrix::kMTransY));
690 m[6] = SkScalarToFloat(matrix->get(SkMatrix::kMPersp0));
691 m[7] = SkScalarToFloat(matrix->get(SkMatrix::kMPersp1));
692 m[8] = SkScalarToFloat(matrix->get(SkMatrix::kMPersp2));
696 static jint android_view_MotionEvent_nativeReadFromParcel(JNIEnv* env, jclass clazz,
697 jint nativePtr, jobject parcelObj) {
698 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
700 event = new MotionEvent();
703 Parcel* parcel = parcelForJavaObject(env, parcelObj);
705 status_t status = event->readFromParcel(parcel);
710 jniThrowRuntimeException(env, "Failed to read MotionEvent parcel.");
713 return reinterpret_cast<jint>(event);
716 static void android_view_MotionEvent_nativeWriteToParcel(JNIEnv* env, jclass clazz,
717 jint nativePtr, jobject parcelObj) {
718 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
719 Parcel* parcel = parcelForJavaObject(env, parcelObj);
721 status_t status = event->writeToParcel(parcel);
723 jniThrowRuntimeException(env, "Failed to write MotionEvent parcel.");
727 // ----------------------------------------------------------------------------
729 static JNINativeMethod gMotionEventMethods[] = {
730 /* name, signature, funcPtr */
731 { "nativeInitialize",
732 "(IIIIIIIIFFFFJJI[Landroid/view/MotionEvent$PointerProperties;"
733 "[Landroid/view/MotionEvent$PointerCoords;)I",
734 (void*)android_view_MotionEvent_nativeInitialize },
737 (void*)android_view_MotionEvent_nativeCopy },
740 (void*)android_view_MotionEvent_nativeDispose },
742 "(IJ[Landroid/view/MotionEvent$PointerCoords;I)V",
743 (void*)android_view_MotionEvent_nativeAddBatch },
744 { "nativeGetDeviceId",
746 (void*)android_view_MotionEvent_nativeGetDeviceId },
749 (void*)android_view_MotionEvent_nativeGetSource },
752 (void*)android_view_MotionEvent_nativeSetSource },
755 (void*)android_view_MotionEvent_nativeGetAction },
758 (void*)android_view_MotionEvent_nativeSetAction },
759 { "nativeIsTouchEvent",
761 (void*)android_view_MotionEvent_nativeIsTouchEvent },
764 (void*)android_view_MotionEvent_nativeGetFlags },
767 (void*)android_view_MotionEvent_nativeSetFlags },
768 { "nativeGetEdgeFlags",
770 (void*)android_view_MotionEvent_nativeGetEdgeFlags },
771 { "nativeSetEdgeFlags",
773 (void*)android_view_MotionEvent_nativeSetEdgeFlags },
774 { "nativeGetMetaState",
776 (void*)android_view_MotionEvent_nativeGetMetaState },
777 { "nativeGetButtonState",
779 (void*)android_view_MotionEvent_nativeGetButtonState },
780 { "nativeOffsetLocation",
782 (void*)android_view_MotionEvent_nativeOffsetLocation },
783 { "nativeGetXOffset",
785 (void*)android_view_MotionEvent_nativeGetXOffset },
786 { "nativeGetYOffset",
788 (void*)android_view_MotionEvent_nativeGetYOffset },
789 { "nativeGetXPrecision",
791 (void*)android_view_MotionEvent_nativeGetXPrecision },
792 { "nativeGetYPrecision",
794 (void*)android_view_MotionEvent_nativeGetYPrecision },
795 { "nativeGetDownTimeNanos",
797 (void*)android_view_MotionEvent_nativeGetDownTimeNanos },
798 { "nativeSetDownTimeNanos",
800 (void*)android_view_MotionEvent_nativeSetDownTimeNanos },
801 { "nativeGetPointerCount",
803 (void*)android_view_MotionEvent_nativeGetPointerCount },
804 { "nativeGetPointerId",
806 (void*)android_view_MotionEvent_nativeGetPointerId },
807 { "nativeGetToolType",
809 (void*)android_view_MotionEvent_nativeGetToolType },
810 { "nativeFindPointerIndex",
812 (void*)android_view_MotionEvent_nativeFindPointerIndex },
813 { "nativeGetHistorySize",
815 (void*)android_view_MotionEvent_nativeGetHistorySize },
816 { "nativeGetEventTimeNanos",
818 (void*)android_view_MotionEvent_nativeGetEventTimeNanos },
819 { "nativeGetRawAxisValue",
821 (void*)android_view_MotionEvent_nativeGetRawAxisValue },
822 { "nativeGetAxisValue",
824 (void*)android_view_MotionEvent_nativeGetAxisValue },
825 { "nativeGetPointerCoords",
826 "(IIILandroid/view/MotionEvent$PointerCoords;)V",
827 (void*)android_view_MotionEvent_nativeGetPointerCoords },
828 { "nativeGetPointerProperties",
829 "(IILandroid/view/MotionEvent$PointerProperties;)V",
830 (void*)android_view_MotionEvent_nativeGetPointerProperties },
833 (void*)android_view_MotionEvent_nativeScale },
835 "(ILandroid/graphics/Matrix;)V",
836 (void*)android_view_MotionEvent_nativeTransform },
837 { "nativeReadFromParcel",
838 "(ILandroid/os/Parcel;)I",
839 (void*)android_view_MotionEvent_nativeReadFromParcel },
840 { "nativeWriteToParcel",
841 "(ILandroid/os/Parcel;)V",
842 (void*)android_view_MotionEvent_nativeWriteToParcel },
845 #define FIND_CLASS(var, className) \
846 var = env->FindClass(className); \
847 LOG_FATAL_IF(! var, "Unable to find class " className);
849 #define GET_STATIC_METHOD_ID(var, clazz, methodName, fieldDescriptor) \
850 var = env->GetStaticMethodID(clazz, methodName, fieldDescriptor); \
851 LOG_FATAL_IF(! var, "Unable to find static method" methodName);
853 #define GET_METHOD_ID(var, clazz, methodName, fieldDescriptor) \
854 var = env->GetMethodID(clazz, methodName, fieldDescriptor); \
855 LOG_FATAL_IF(! var, "Unable to find method" methodName);
857 #define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
858 var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \
859 LOG_FATAL_IF(! var, "Unable to find field " fieldName);
861 int register_android_view_MotionEvent(JNIEnv* env) {
862 int res = jniRegisterNativeMethods(env, "android/view/MotionEvent",
863 gMotionEventMethods, NELEM(gMotionEventMethods));
864 LOG_FATAL_IF(res < 0, "Unable to register native methods.");
866 FIND_CLASS(gMotionEventClassInfo.clazz, "android/view/MotionEvent");
867 gMotionEventClassInfo.clazz = jclass(env->NewGlobalRef(gMotionEventClassInfo.clazz));
869 GET_STATIC_METHOD_ID(gMotionEventClassInfo.obtain, gMotionEventClassInfo.clazz,
870 "obtain", "()Landroid/view/MotionEvent;");
871 GET_METHOD_ID(gMotionEventClassInfo.recycle, gMotionEventClassInfo.clazz,
873 GET_FIELD_ID(gMotionEventClassInfo.mNativePtr, gMotionEventClassInfo.clazz,
877 FIND_CLASS(clazz, "android/view/MotionEvent$PointerCoords");
879 GET_FIELD_ID(gPointerCoordsClassInfo.mPackedAxisBits, clazz,
880 "mPackedAxisBits", "J");
881 GET_FIELD_ID(gPointerCoordsClassInfo.mPackedAxisValues, clazz,
882 "mPackedAxisValues", "[F");
883 GET_FIELD_ID(gPointerCoordsClassInfo.x, clazz,
885 GET_FIELD_ID(gPointerCoordsClassInfo.y, clazz,
887 GET_FIELD_ID(gPointerCoordsClassInfo.pressure, clazz,
889 GET_FIELD_ID(gPointerCoordsClassInfo.size, clazz,
891 GET_FIELD_ID(gPointerCoordsClassInfo.touchMajor, clazz,
893 GET_FIELD_ID(gPointerCoordsClassInfo.touchMinor, clazz,
895 GET_FIELD_ID(gPointerCoordsClassInfo.toolMajor, clazz,
897 GET_FIELD_ID(gPointerCoordsClassInfo.toolMinor, clazz,
899 GET_FIELD_ID(gPointerCoordsClassInfo.orientation, clazz,
902 FIND_CLASS(clazz, "android/view/MotionEvent$PointerProperties");
904 GET_FIELD_ID(gPointerPropertiesClassInfo.id, clazz,
906 GET_FIELD_ID(gPointerPropertiesClassInfo.toolType, clazz,
912 } // namespace android