Last active
June 6, 2021 21:10
-
-
Save mgood7123/5d339da06fb2fd32f1df732996b5fdaf to your computer and use it in GitHub Desktop.
MotionEvent Java->JNI
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// Created by Matthew Good on 7/6/21. | |
// | |
#include "MotionEventSerializer.h" | |
MotionEventSerializer::IndexInfo::IndexInfo() {} | |
MotionEventSerializer::IndexInfo::IndexInfo(int pointerIndex, int segment_length, int reserved) { | |
idx_pointerId = (pointerIndex*segment_length)+reserved; | |
idx_ptrIndex = (pointerIndex*segment_length)+reserved+1; | |
idx_active = (pointerIndex*segment_length)+reserved+2; | |
idx_action = (pointerIndex*segment_length)+reserved+3; | |
idx_moved = (pointerIndex*segment_length)+reserved+4; | |
idx_x = (pointerIndex*segment_length)+reserved+5; | |
idx_y = (pointerIndex*segment_length)+reserved+6; | |
idx_pressure = (pointerIndex*segment_length)+reserved+7; | |
idx_size = (pointerIndex*segment_length)+reserved+8; | |
} | |
void MotionEventSerializer::acquire(JNIEnv *jenv, jfloatArray motionEventData) { | |
jboolean isCopy; | |
data = jenv->GetFloatArrayElements(motionEventData, &isCopy); | |
dataLength = data[idx_dataLength]; | |
reserved = data[idx_dataReserved]; | |
segment_length = data[idx_dataSegmentLength]; | |
maxSupportedPointers = data[idx_maxSupportedPointers]; | |
int c = pointerCount(); | |
indexInfo = new IndexInfo[c]; | |
for (int i = 0; i < c; i++) { | |
indexInfo[i] = IndexInfo(i, segment_length, reserved); | |
} | |
} | |
void MotionEventSerializer::release(JNIEnv *jenv, jfloatArray motionEventData) { | |
delete[] indexInfo; | |
jenv->ReleaseFloatArrayElements(motionEventData, data, 0); | |
data = nullptr; | |
} | |
int MotionEventSerializer::pointerCount() { | |
return data[idx_ptrCount]; | |
} | |
int MotionEventSerializer::currentPointerIndex() { | |
return data[idx_ptrCurrentIdx]; | |
} | |
int MotionEventSerializer::getActionIndex() { | |
return currentPointerIndex(); | |
} | |
int MotionEventSerializer::getPointerId(int pointerIndex) { | |
return data[indexInfo[pointerIndex].idx_pointerId]; | |
} | |
bool MotionEventSerializer::isPointerActive(int pointerIndex) { | |
return data[indexInfo[pointerIndex].idx_active] == MOTION_EVENT_ACTIVE; | |
} | |
int MotionEventSerializer::getAction(int pointerIndex) { | |
return data[indexInfo[pointerIndex].idx_action]; | |
} | |
bool MotionEventSerializer::didPointerMove(int pointerIndex) { | |
return data[indexInfo[pointerIndex].idx_moved] == MOTION_EVENT_MOVED; | |
} | |
float MotionEventSerializer::getX(int pointerIndex) { | |
return data[indexInfo[pointerIndex].idx_x]; | |
} | |
float MotionEventSerializer::getY(int pointerIndex) { | |
return data[indexInfo[pointerIndex].idx_y]; | |
} | |
float MotionEventSerializer::getPressure(int pointerIndex) { | |
return data[indexInfo[pointerIndex].idx_pressure]; | |
} | |
float MotionEventSerializer::getSize(int pointerIndex) { | |
return data[indexInfo[pointerIndex].idx_size]; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// Created by Matthew Good on 7/6/21. | |
// | |
#ifndef CRAFTER_MOTIONEVENTSERIALIZER_H | |
#define CRAFTER_MOTIONEVENTSERIALIZER_H | |
#include <jni.h> | |
class MotionEventSerializer { | |
private: | |
class IndexInfo { | |
public: | |
int idx_pointerId; | |
int idx_ptrIndex; | |
int idx_active; | |
int idx_action; | |
int idx_moved; | |
int idx_x; | |
int idx_y; | |
int idx_pressure; | |
int idx_size; | |
IndexInfo(); | |
IndexInfo(int pointerIndex, int segment_length, int reserved); | |
}; | |
IndexInfo * indexInfo; | |
int reserved; | |
int segment_length; | |
int maxSupportedPointers; | |
int dataLength; | |
float * data = nullptr; | |
// THESE MUSE BE KEPT IN SYNC WITH JAVA SIDE | |
static const int idx_dataLength = 0; | |
static const int idx_dataReserved = 1; | |
static const int idx_dataSegmentLength = 2; | |
static const int idx_maxSupportedPointers = 3; | |
static const int idx_ptrCount = 4; | |
static const int idx_ptrCurrentIdx = 5; | |
public: | |
// THESE MUSE BE KEPT IN SYNC WITH JAVA SIDE | |
static const int MOTION_EVENT_ACTIVE = 1; | |
static const int MOTION_EVENT_NOT_ACTIVE = 2; | |
static const int MOTION_EVENT_ACTION_UNKNOWN = -1; | |
static const int MOTION_EVENT_ACTION_DOWN = 1; | |
static const int MOTION_EVENT_ACTION_UP = 2; | |
static const int MOTION_EVENT_ACTION_MOVE = 3; | |
static const int MOTION_EVENT_MOVED = 1; | |
static const int MOTION_EVENT_DID_NOT_MOVE = 2; | |
void acquire(JNIEnv *jenv, jfloatArray motionEventData); | |
void release(JNIEnv *jenv, jfloatArray motionEventData); | |
int pointerCount(); | |
int currentPointerIndex(); | |
bool isPointerActive(int pointerIndex); | |
bool didPointerMove(int pointerIndex); | |
int getPointerId(int pointerIndex); | |
int getAction(int pointerIndex); | |
int getActionIndex(); | |
float getX(int pointerIndex); | |
float getY(int pointerIndex); | |
float getPressure(int pointerIndex); | |
float getSize(int pointerIndex); | |
}; | |
#endif //CRAFTER_MOTIONEVENTSERIALIZER_H |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import android.view.MotionEvent; | |
import java.util.Arrays; | |
public class MotionEventSerializer { | |
private static final String TAG = "MotionEventSerializer"; | |
private final int reserved = 6; | |
private final int segment_length = 9; | |
private final int maxSupportedPointers; | |
private final int dataLength; | |
public final float[] data; | |
/** | |
* @param maxSupportedPointers must be kept equal with JNI Side | |
*/ | |
MotionEventSerializer(int maxSupportedPointers) { | |
this.maxSupportedPointers = maxSupportedPointers; | |
dataLength = reserved + (segment_length * maxSupportedPointers); | |
data = new float[dataLength]; | |
Arrays.fill(data, 0.0f); | |
} | |
// THESE MUSE BE KEPT IN SYNC WITH JNI SIDE | |
private static final int MOTION_EVENT_ACTIVE = 1; | |
private static final int MOTION_EVENT_NOT_ACTIVE = 2; | |
private static final int MOTION_EVENT_ACTION_UNKNOWN = -1; | |
private static final int MOTION_EVENT_ACTION_DOWN = 1; | |
private static final int MOTION_EVENT_ACTION_UP = 2; | |
private static final int MOTION_EVENT_ACTION_MOVE = 3; | |
private static final int MOTION_EVENT_MOVED = 1; | |
private static final int MOTION_EVENT_DID_NOT_MOVE = 2; | |
private static final int idx_dataLength = 0; | |
private static final int idx_dataReserved = 1; | |
private static final int idx_dataSegmentLength = 2; | |
private static final int idx_maxSupportedPointers = 3; | |
private static final int idx_ptrCount = 4; | |
private static final int idx_ptrCurrentIdx = 5; | |
/** | |
* MotionEvent <br> | |
* MOTION_EVENT_ACTION_UP and MOTION_EVENT_ACTION_DOWN | |
* always happen sequentially <br><br> | |
* | |
* MotionEvent <br> | |
* MOTION_EVENT_ACTION_MOVE can occur at the same time | |
* and are merged into single events when possible<br><br> | |
* | |
* provides basic pointer tracking by marking which pointers | |
* are currently active and which pointers have moved<br><br> | |
* | |
* public functions in jni side:<br> | |
* <li> void acquire(JNIEnv *jenv, jfloatArray motionEventData); | |
* <li> void release(JNIEnv *jenv, jfloatArray motionEventData); | |
* <br><br> | |
* <li> int pointerCount(); | |
* <li> int currentPointerIndex(); | |
* <br><br> | |
* <li> bool isPointerActive(int pointerIndex); | |
* <li> bool didPointerMove(int pointerIndex); | |
* <br><br> | |
* <li> int getPointerId(int pointerIndex); | |
* <li> int getAction(int pointerIndex); | |
* <li> int getActionIndex(); | |
* <li> float getX(int pointerIndex); | |
* <li> float getY(int pointerIndex); | |
* <li> float getPressure(int pointerIndex); | |
* <li> float getSize(int pointerIndex); | |
*/ | |
public float[] process(MotionEvent event) { | |
int pointerCount = event.getPointerCount(); | |
int action = event.getActionMasked(); | |
int pointerIndex = event.getActionIndex(); | |
int pointerId = event.getPointerId(pointerIndex); | |
data[idx_dataLength] = dataLength; | |
data[idx_dataReserved] = reserved; | |
data[idx_dataSegmentLength] = segment_length; | |
data[idx_maxSupportedPointers] = maxSupportedPointers; | |
data[idx_ptrCount] = pointerCount; | |
data[idx_ptrCurrentIdx] = pointerIndex; | |
int idx_pointerId = (pointerIndex*segment_length)+reserved; | |
int idx_ptrIndex = (pointerIndex*segment_length)+reserved+1; | |
int idx_action = (pointerIndex*segment_length)+reserved+3; | |
int idx_active = (pointerIndex*segment_length)+reserved+2; | |
data[idx_pointerId] = pointerId; | |
data[idx_ptrIndex] = pointerIndex; | |
switch (action) { | |
case MotionEvent.ACTION_DOWN: | |
case MotionEvent.ACTION_POINTER_DOWN: | |
data[idx_active] = MOTION_EVENT_ACTIVE; | |
data[idx_action] = MOTION_EVENT_ACTION_DOWN; | |
break; | |
case MotionEvent.ACTION_MOVE: | |
break; | |
case MotionEvent.ACTION_UP: | |
case MotionEvent.ACTION_POINTER_UP: | |
data[idx_active] = MOTION_EVENT_NOT_ACTIVE; | |
data[idx_action] = MOTION_EVENT_ACTION_UP; | |
break; | |
default: | |
data[idx_action] = MOTION_EVENT_ACTION_UNKNOWN; | |
break; | |
} | |
for (int i = 0; i < pointerCount; i++) { | |
if (data[(i*segment_length)+reserved+2] == MOTION_EVENT_ACTIVE) { | |
int idx_moved = (i*segment_length)+reserved+4; | |
int idx_x = (i*segment_length)+reserved+5; | |
int idx_y = (i*segment_length)+reserved+6; | |
int idx_pressure = (i*segment_length)+reserved+7; | |
int idx_size = (i*segment_length)+reserved+8; | |
float x = event.getX(i); | |
float y = event.getY(i); | |
if (data[idx_x] != x || data[idx_y] != y) { | |
data[idx_x] = x; | |
data[idx_y] = y; | |
data[(i*segment_length)+reserved+3] = MOTION_EVENT_ACTION_MOVE; | |
data[idx_moved] = MOTION_EVENT_MOVED; | |
} else { | |
data[idx_moved] = MOTION_EVENT_DID_NOT_MOVE; | |
} | |
data[idx_pressure] = event.getPressure(i); | |
data[idx_size] = event.getSize(i); | |
} | |
} | |
return data; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment