Merge change 9649
* changes: Finish implementation of multiple pointer support for MotionEvent.
This commit is contained in:
@@ -145940,6 +145940,19 @@
|
||||
visibility="public"
|
||||
>
|
||||
</method>
|
||||
<method name="findPointerIndex"
|
||||
return="int"
|
||||
abstract="false"
|
||||
native="false"
|
||||
synchronized="false"
|
||||
static="false"
|
||||
final="true"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
<parameter name="pointerId" type="int">
|
||||
</parameter>
|
||||
</method>
|
||||
<method name="getAction"
|
||||
return="int"
|
||||
abstract="false"
|
||||
@@ -146031,7 +146044,7 @@
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
<parameter name="pointer" type="int">
|
||||
<parameter name="pointerIndex" type="int">
|
||||
</parameter>
|
||||
<parameter name="pos" type="int">
|
||||
</parameter>
|
||||
@@ -146059,7 +146072,7 @@
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
<parameter name="pointer" type="int">
|
||||
<parameter name="pointerIndex" type="int">
|
||||
</parameter>
|
||||
<parameter name="pos" type="int">
|
||||
</parameter>
|
||||
@@ -146087,7 +146100,7 @@
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
<parameter name="pointer" type="int">
|
||||
<parameter name="pointerIndex" type="int">
|
||||
</parameter>
|
||||
<parameter name="pos" type="int">
|
||||
</parameter>
|
||||
@@ -146115,7 +146128,7 @@
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
<parameter name="pointer" type="int">
|
||||
<parameter name="pointerIndex" type="int">
|
||||
</parameter>
|
||||
<parameter name="pos" type="int">
|
||||
</parameter>
|
||||
@@ -146153,6 +146166,19 @@
|
||||
visibility="public"
|
||||
>
|
||||
</method>
|
||||
<method name="getPointerId"
|
||||
return="int"
|
||||
abstract="false"
|
||||
native="false"
|
||||
synchronized="false"
|
||||
static="false"
|
||||
final="true"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
<parameter name="index" type="int">
|
||||
</parameter>
|
||||
</method>
|
||||
<method name="getPressure"
|
||||
return="float"
|
||||
abstract="false"
|
||||
@@ -146174,7 +146200,7 @@
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
<parameter name="pointer" type="int">
|
||||
<parameter name="pointerIndex" type="int">
|
||||
</parameter>
|
||||
</method>
|
||||
<method name="getRawX"
|
||||
@@ -146220,7 +146246,7 @@
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
<parameter name="pointer" type="int">
|
||||
<parameter name="pointerIndex" type="int">
|
||||
</parameter>
|
||||
</method>
|
||||
<method name="getX"
|
||||
@@ -146244,7 +146270,7 @@
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
<parameter name="pointer" type="int">
|
||||
<parameter name="pointerIndex" type="int">
|
||||
</parameter>
|
||||
</method>
|
||||
<method name="getXPrecision"
|
||||
@@ -146279,7 +146305,7 @@
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
<parameter name="pointer" type="int">
|
||||
<parameter name="pointerIndex" type="int">
|
||||
</parameter>
|
||||
</method>
|
||||
<method name="getYPrecision"
|
||||
@@ -146615,7 +146641,7 @@
|
||||
visibility="public"
|
||||
>
|
||||
</field>
|
||||
<field name="ACTION_POINTER_MASK"
|
||||
<field name="ACTION_POINTER_ID_MASK"
|
||||
type="int"
|
||||
transient="false"
|
||||
volatile="false"
|
||||
@@ -146626,7 +146652,7 @@
|
||||
visibility="public"
|
||||
>
|
||||
</field>
|
||||
<field name="ACTION_POINTER_SHIFT"
|
||||
<field name="ACTION_POINTER_ID_SHIFT"
|
||||
type="int"
|
||||
transient="false"
|
||||
volatile="false"
|
||||
|
||||
@@ -19,6 +19,7 @@ package android.view;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.os.SystemClock;
|
||||
import android.util.Log;
|
||||
|
||||
/**
|
||||
* Object used to report movement (mouse, pen, finger, trackball) events. This
|
||||
@@ -26,6 +27,8 @@ import android.os.SystemClock;
|
||||
* it is being used for.
|
||||
*/
|
||||
public final class MotionEvent implements Parcelable {
|
||||
static final boolean DEBUG_POINTERS = false;
|
||||
|
||||
/**
|
||||
* Bit mask of the parts of the action code that are the action itself.
|
||||
*/
|
||||
@@ -68,58 +71,67 @@ public final class MotionEvent implements Parcelable {
|
||||
|
||||
/**
|
||||
* A non-primary pointer has gone down. The bits in
|
||||
* {@link #ACTION_POINTER_MASK} indicate which pointer changed.
|
||||
* {@link #ACTION_POINTER_ID_MASK} indicate which pointer changed.
|
||||
*/
|
||||
public static final int ACTION_POINTER_DOWN = 5;
|
||||
|
||||
/**
|
||||
* The primary pointer has gone done.
|
||||
* Synonym for {@link #ACTION_POINTER_DOWN} with
|
||||
* {@link #ACTION_POINTER_ID_MASK} of 0: the primary pointer has gone done.
|
||||
*/
|
||||
public static final int ACTION_POINTER_1_DOWN = ACTION_POINTER_DOWN | 0x0000;
|
||||
|
||||
/**
|
||||
* The secondary pointer has gone done.
|
||||
* Synonym for {@link #ACTION_POINTER_DOWN} with
|
||||
* {@link #ACTION_POINTER_ID_MASK} of 1: the secondary pointer has gone done.
|
||||
*/
|
||||
public static final int ACTION_POINTER_2_DOWN = ACTION_POINTER_DOWN | 0x0100;
|
||||
|
||||
/**
|
||||
* The tertiary pointer has gone done.
|
||||
* Synonym for {@link #ACTION_POINTER_DOWN} with
|
||||
* {@link #ACTION_POINTER_ID_MASK} of 2: the tertiary pointer has gone done.
|
||||
*/
|
||||
public static final int ACTION_POINTER_3_DOWN = ACTION_POINTER_DOWN | 0x0200;
|
||||
|
||||
/**
|
||||
* A non-primary pointer has gone up. The bits in
|
||||
* {@link #ACTION_POINTER_MASK} indicate which pointer changed.
|
||||
* {@link #ACTION_POINTER_ID_MASK} indicate which pointer changed.
|
||||
*/
|
||||
public static final int ACTION_POINTER_UP = 6;
|
||||
|
||||
/**
|
||||
* The primary pointer has gone up.
|
||||
* Synonym for {@link #ACTION_POINTER_UP} with
|
||||
* {@link #ACTION_POINTER_ID_MASK} of 0: the primary pointer has gone up.
|
||||
*/
|
||||
public static final int ACTION_POINTER_1_UP = ACTION_POINTER_UP | 0x0000;
|
||||
|
||||
/**
|
||||
* The secondary pointer has gone up.
|
||||
* Synonym for {@link #ACTION_POINTER_UP} with
|
||||
* {@link #ACTION_POINTER_ID_MASK} of 1: the secondary pointer has gone up.
|
||||
*/
|
||||
public static final int ACTION_POINTER_2_UP = ACTION_POINTER_UP | 0x0100;
|
||||
|
||||
/**
|
||||
* The tertiary pointer has gone up.
|
||||
* Synonym for {@link #ACTION_POINTER_UP} with
|
||||
* {@link #ACTION_POINTER_ID_MASK} of 2: the tertiary pointer has gone up.
|
||||
*/
|
||||
public static final int ACTION_POINTER_3_UP = ACTION_POINTER_UP | 0x0200;
|
||||
|
||||
/**
|
||||
* Bits in the action code that represent a pointer ID, used with
|
||||
* {@link #ACTION_POINTER_DOWN} and {@link #ACTION_POINTER_UP}. Pointer IDs
|
||||
* start at 0, with 0 being the primary (first) pointer in the motion.
|
||||
* start at 0, with 0 being the primary (first) pointer in the motion. Note
|
||||
* that this not <em>not</em> an index into the array of pointer values,
|
||||
* which is compacted to only contain pointers that are down; the pointer
|
||||
* ID for a particular index can be found with {@link #findPointerIndex}.
|
||||
*/
|
||||
public static final int ACTION_POINTER_MASK = 0xff00;
|
||||
public static final int ACTION_POINTER_ID_MASK = 0xff00;
|
||||
|
||||
/**
|
||||
* Bit shift for the action bits holding the pointer identifier as
|
||||
* defined by {@link #ACTION_POINTER_MASK}.
|
||||
* defined by {@link #ACTION_POINTER_ID_MASK}.
|
||||
*/
|
||||
public static final int ACTION_POINTER_SHIFT = 8;
|
||||
public static final int ACTION_POINTER_ID_SHIFT = 8;
|
||||
|
||||
private static final boolean TRACK_RECYCLED_LOCATION = false;
|
||||
|
||||
@@ -143,18 +155,6 @@ public final class MotionEvent implements Parcelable {
|
||||
*/
|
||||
public static final int EDGE_RIGHT = 0x00000008;
|
||||
|
||||
/**
|
||||
* This is the part of the state data that holds the finger identifier
|
||||
* for the sample.
|
||||
*/
|
||||
static private final int STATE_FINGER_ID_MASK = 0xff;
|
||||
|
||||
/**
|
||||
* Special value for STATE_FINGER_ID_MASK indicating that the finger
|
||||
* is not down in that sample.
|
||||
*/
|
||||
static private final int STATE_FINGER_ID_NONE = 0xff;
|
||||
|
||||
/**
|
||||
* Offset for the sample's X coordinate.
|
||||
* @hide
|
||||
@@ -212,8 +212,8 @@ public final class MotionEvent implements Parcelable {
|
||||
|
||||
private int mNumPointers;
|
||||
private int mNumSamples;
|
||||
// Array of (mNumSamples * mNumPointers) size of control data.
|
||||
private int[] mStateSamples;
|
||||
// Array of mNumPointers size of identifiers for each pointer of data.
|
||||
private int[] mPointerIdentifiers;
|
||||
// Array of (mNumSamples * mNumPointers * NUM_SAMPLE_DATA) size of event data.
|
||||
private float[] mDataSamples;
|
||||
// Array of mNumSamples size of time stamps.
|
||||
@@ -224,7 +224,7 @@ public final class MotionEvent implements Parcelable {
|
||||
private boolean mRecycled;
|
||||
|
||||
private MotionEvent() {
|
||||
mStateSamples = new int[BASE_AVAIL_POINTERS*BASE_AVAIL_SAMPLES];
|
||||
mPointerIdentifiers = new int[BASE_AVAIL_POINTERS];
|
||||
mDataSamples = new float[BASE_AVAIL_POINTERS*BASE_AVAIL_SAMPLES*NUM_SAMPLE_DATA];
|
||||
mTimeSamples = new long[BASE_AVAIL_SAMPLES];
|
||||
}
|
||||
@@ -256,16 +256,11 @@ public final class MotionEvent implements Parcelable {
|
||||
* @param action The kind of action being performed -- one of either
|
||||
* {@link #ACTION_DOWN}, {@link #ACTION_MOVE}, {@link #ACTION_UP}, or
|
||||
* {@link #ACTION_CANCEL}.
|
||||
* @param x The X coordinate of this event.
|
||||
* @param y The Y coordinate of this event.
|
||||
* @param pressure The current pressure of this event. The pressure generally
|
||||
* ranges from 0 (no pressure at all) to 1 (normal pressure), however
|
||||
* values higher than 1 may be generated depending on the calibration of
|
||||
* the input device.
|
||||
* @param size A scaled value of the approximate size of the area being pressed when
|
||||
* touched with the finger. The actual value in pixels corresponding to the finger
|
||||
* touch is normalized with a device specific range of values
|
||||
* and scaled to a value between 0 and 1.
|
||||
* @param pointers The number of points that will be in this event.
|
||||
* @param inPointerIds An array of <em>pointers</em> values providing
|
||||
* an identifier for each pointer.
|
||||
* @param inData An array of <em>pointers*NUM_SAMPLE_DATA</em> of initial
|
||||
* data samples for the event.
|
||||
* @param metaState The state of any meta / modifier keys that were in effect when
|
||||
* the event was generated.
|
||||
* @param xPrecision The precision of the X coordinate being reported.
|
||||
@@ -279,7 +274,7 @@ public final class MotionEvent implements Parcelable {
|
||||
* @hide
|
||||
*/
|
||||
static public MotionEvent obtainNano(long downTime, long eventTime, long eventTimeNano,
|
||||
int action, int pointers, float[] inData, int metaState,
|
||||
int action, int pointers, int[] inPointerIds, float[] inData, int metaState,
|
||||
float xPrecision, float yPrecision, int deviceId, int edgeFlags) {
|
||||
MotionEvent ev = obtain();
|
||||
ev.mDeviceId = deviceId;
|
||||
@@ -295,17 +290,25 @@ public final class MotionEvent implements Parcelable {
|
||||
ev.mNumPointers = pointers;
|
||||
ev.mNumSamples = 1;
|
||||
|
||||
float[] data = ev.mDataSamples;
|
||||
System.arraycopy(inData, 0, data, 0, pointers * NUM_SAMPLE_DATA);
|
||||
|
||||
int[] state = ev.mStateSamples;
|
||||
while (pointers > 0) {
|
||||
pointers--;
|
||||
state[pointers] = pointers;
|
||||
}
|
||||
|
||||
System.arraycopy(inPointerIds, 0, ev.mPointerIdentifiers, 0, pointers);
|
||||
System.arraycopy(inData, 0, ev.mDataSamples, 0, pointers * NUM_SAMPLE_DATA);
|
||||
ev.mTimeSamples[0] = eventTime;
|
||||
|
||||
if (DEBUG_POINTERS) {
|
||||
StringBuilder sb = new StringBuilder(128);
|
||||
sb.append("New:");
|
||||
for (int i=0; i<pointers; i++) {
|
||||
sb.append(" #");
|
||||
sb.append(ev.mPointerIdentifiers[i]);
|
||||
sb.append("(");
|
||||
sb.append(ev.mDataSamples[(i*NUM_SAMPLE_DATA) + SAMPLE_X]);
|
||||
sb.append(",");
|
||||
sb.append(ev.mDataSamples[(i*NUM_SAMPLE_DATA) + SAMPLE_Y]);
|
||||
sb.append(")");
|
||||
}
|
||||
Log.v("MotionEvent", sb.toString());
|
||||
}
|
||||
|
||||
return ev;
|
||||
}
|
||||
|
||||
@@ -355,8 +358,8 @@ public final class MotionEvent implements Parcelable {
|
||||
|
||||
ev.mNumPointers = 1;
|
||||
ev.mNumSamples = 1;
|
||||
int[] state = ev.mStateSamples;
|
||||
state[0] = 0;
|
||||
int[] pointerIds = ev.mPointerIdentifiers;
|
||||
pointerIds[0] = 0;
|
||||
float[] data = ev.mDataSamples;
|
||||
data[SAMPLE_X] = ev.mRawX = x;
|
||||
data[SAMPLE_Y] = ev.mRawY = y;
|
||||
@@ -415,8 +418,8 @@ public final class MotionEvent implements Parcelable {
|
||||
|
||||
ev.mNumPointers = 1;
|
||||
ev.mNumSamples = 1;
|
||||
int[] state = ev.mStateSamples;
|
||||
state[0] = 0;
|
||||
int[] pointerIds = ev.mPointerIdentifiers;
|
||||
pointerIds[0] = 0;
|
||||
float[] data = ev.mDataSamples;
|
||||
data[SAMPLE_X] = ev.mRawX = x;
|
||||
data[SAMPLE_Y] = ev.mRawY = y;
|
||||
@@ -459,8 +462,8 @@ public final class MotionEvent implements Parcelable {
|
||||
|
||||
ev.mNumPointers = 1;
|
||||
ev.mNumSamples = 1;
|
||||
int[] state = ev.mStateSamples;
|
||||
state[0] = 0;
|
||||
int[] pointerIds = ev.mPointerIdentifiers;
|
||||
pointerIds[0] = 0;
|
||||
float[] data = ev.mDataSamples;
|
||||
data[SAMPLE_X] = ev.mRawX = x;
|
||||
data[SAMPLE_Y] = ev.mRawY = y;
|
||||
@@ -508,21 +511,21 @@ public final class MotionEvent implements Parcelable {
|
||||
ev.mXPrecision = o.mXPrecision;
|
||||
ev.mYPrecision = o.mYPrecision;
|
||||
|
||||
final int NT = ev.mNumSamples = o.mNumSamples;
|
||||
if (ev.mTimeSamples.length >= NT) {
|
||||
System.arraycopy(o.mTimeSamples, 0, ev.mTimeSamples, 0, NT);
|
||||
final int NS = ev.mNumSamples = o.mNumSamples;
|
||||
if (ev.mTimeSamples.length >= NS) {
|
||||
System.arraycopy(o.mTimeSamples, 0, ev.mTimeSamples, 0, NS);
|
||||
} else {
|
||||
ev.mTimeSamples = (long[])o.mTimeSamples.clone();
|
||||
}
|
||||
|
||||
final int NS = (ev.mNumPointers=o.mNumPointers) * NT;
|
||||
if (ev.mStateSamples.length >= NS) {
|
||||
System.arraycopy(o.mStateSamples, 0, ev.mStateSamples, 0, NS);
|
||||
final int NP = (ev.mNumPointers=o.mNumPointers);
|
||||
if (ev.mPointerIdentifiers.length >= NP) {
|
||||
System.arraycopy(o.mPointerIdentifiers, 0, ev.mPointerIdentifiers, 0, NP);
|
||||
} else {
|
||||
ev.mStateSamples = (int[])o.mStateSamples.clone();
|
||||
ev.mPointerIdentifiers = (int[])o.mPointerIdentifiers.clone();
|
||||
}
|
||||
|
||||
final int ND = NS * NUM_SAMPLE_DATA;
|
||||
final int ND = NP * NS * NUM_SAMPLE_DATA;
|
||||
if (ev.mDataSamples.length >= ND) {
|
||||
System.arraycopy(o.mDataSamples, 0, ev.mDataSamples, 0, ND);
|
||||
} else {
|
||||
@@ -592,6 +595,38 @@ public final class MotionEvent implements Parcelable {
|
||||
return mEventTimeNano;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link #getX(int)} for the first pointer index (may be an
|
||||
* arbitrary pointer identifier).
|
||||
*/
|
||||
public final float getX() {
|
||||
return mDataSamples[SAMPLE_X];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link #getY(int)} for the first pointer index (may be an
|
||||
* arbitrary pointer identifier).
|
||||
*/
|
||||
public final float getY() {
|
||||
return mDataSamples[SAMPLE_Y];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link #getPressure(int)} for the first pointer index (may be an
|
||||
* arbitrary pointer identifier).
|
||||
*/
|
||||
public final float getPressure() {
|
||||
return mDataSamples[SAMPLE_PRESSURE];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link #getSize(int)} for the first pointer index (may be an
|
||||
* arbitrary pointer identifier).
|
||||
*/
|
||||
public final float getSize() {
|
||||
return mDataSamples[SAMPLE_SIZE];
|
||||
}
|
||||
|
||||
/**
|
||||
* The number of pointers of data contained in this event. Always
|
||||
* >= 1.
|
||||
@@ -601,80 +636,91 @@ public final class MotionEvent implements Parcelable {
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link #getX(int)} for the first pointer (pointer 0).
|
||||
* Return the pointer identifier associated with a particular pointer
|
||||
* data index is this event. The identifier tells you the actual pointer
|
||||
* number associated with the data, accounting for individual pointers
|
||||
* going up and down since the start of the current gesture.
|
||||
* @param pointerIndex Raw index of pointer to retrieve. Value may be from 0
|
||||
* (the first pointer that is down) to {@link #getPointerCount()}-1.
|
||||
*/
|
||||
public final float getX() {
|
||||
return mDataSamples[SAMPLE_X];
|
||||
public final int getPointerId(int index) {
|
||||
return mPointerIdentifiers[index];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* {@link #getY(int)} for the first pointer (pointer 0).
|
||||
* Given a pointer identifier, find the index of its data in the event.
|
||||
*
|
||||
* @param pointerId The identifier of the pointer to be found.
|
||||
* @return Returns either the index of the pointer (for use with
|
||||
* {@link #getX(int) et al.), or -1 if there is no data available for
|
||||
* that pointer identifier.
|
||||
*/
|
||||
public final float getY() {
|
||||
return mDataSamples[SAMPLE_Y];
|
||||
public final int findPointerIndex(int pointerId) {
|
||||
int i = mNumPointers;
|
||||
while (i > 0) {
|
||||
i--;
|
||||
if (mPointerIdentifiers[i] == pointerId) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* {@link #getPressure(int)} for the first pointer (pointer 0).
|
||||
*/
|
||||
public final float getPressure() {
|
||||
return mDataSamples[SAMPLE_PRESSURE];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link #getSize(int)} for the first pointer (pointer 0).
|
||||
*/
|
||||
public final float getSize() {
|
||||
return mDataSamples[SAMPLE_SIZE];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the X coordinate of this event for the given pointer.
|
||||
* Returns the X coordinate of this event for the given pointer
|
||||
* <em>index</em> (use {@link #getPointerId(int)} to find the pointer
|
||||
* identifier for this index).
|
||||
* Whole numbers are pixels; the
|
||||
* value may have a fraction for input devices that are sub-pixel precise.
|
||||
* @param pointer The desired pointer to retrieve. Value may be from 0
|
||||
* (the first pointer) to {@link #getPointerCount()}-1.
|
||||
* @param pointerIndex Raw index of pointer to retrieve. Value may be from 0
|
||||
* (the first pointer that is down) to {@link #getPointerCount()}-1.
|
||||
*/
|
||||
public final float getX(int pointer) {
|
||||
return mDataSamples[(pointer*NUM_SAMPLE_DATA) + SAMPLE_X];
|
||||
public final float getX(int pointerIndex) {
|
||||
return mDataSamples[(pointerIndex*NUM_SAMPLE_DATA) + SAMPLE_X];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Y coordinate of this event for the given pointer.
|
||||
* Returns the Y coordinate of this event for the given pointer
|
||||
* <em>index</em> (use {@link #getPointerId(int)} to find the pointer
|
||||
* identifier for this index).
|
||||
* Whole numbers are pixels; the
|
||||
* value may have a fraction for input devices that are sub-pixel precise.
|
||||
* @param pointer The desired pointer to retrieve. Value may be from 0
|
||||
* (the first pointer) to {@link #getPointerCount()}-1.
|
||||
* @param pointerIndex Raw index of pointer to retrieve. Value may be from 0
|
||||
* (the first pointer that is down) to {@link #getPointerCount()}-1.
|
||||
*/
|
||||
public final float getY(int pointer) {
|
||||
return mDataSamples[(pointer*NUM_SAMPLE_DATA) + SAMPLE_Y];
|
||||
public final float getY(int pointerIndex) {
|
||||
return mDataSamples[(pointerIndex*NUM_SAMPLE_DATA) + SAMPLE_Y];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current pressure of this event for the given pointer.
|
||||
* Returns the current pressure of this event for the given pointer
|
||||
* <em>index</em> (use {@link #getPointerId(int)} to find the pointer
|
||||
* identifier for this index).
|
||||
* The pressure generally
|
||||
* ranges from 0 (no pressure at all) to 1 (normal pressure), however
|
||||
* values higher than 1 may be generated depending on the calibration of
|
||||
* the input device.
|
||||
* @param pointer The desired pointer to retrieve. Value may be from 0
|
||||
* (the first pointer) to {@link #getPointerCount()}-1.
|
||||
* @param pointerIndex Raw index of pointer to retrieve. Value may be from 0
|
||||
* (the first pointer that is down) to {@link #getPointerCount()}-1.
|
||||
*/
|
||||
public final float getPressure(int pointer) {
|
||||
return mDataSamples[(pointer*NUM_SAMPLE_DATA) + SAMPLE_PRESSURE];
|
||||
public final float getPressure(int pointerIndex) {
|
||||
return mDataSamples[(pointerIndex*NUM_SAMPLE_DATA) + SAMPLE_PRESSURE];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a scaled value of the approximate size for the given pointer,
|
||||
* representing the area of the screen being pressed.
|
||||
* The actual value in pixels corresponding to the
|
||||
* Returns a scaled value of the approximate size for the given pointer
|
||||
* <em>index</em> (use {@link #getPointerId(int)} to find the pointer
|
||||
* identifier for this index).
|
||||
* This represents some approximation of the area of the screen being
|
||||
* pressed; the actual value in pixels corresponding to the
|
||||
* touch is normalized with the device specific range of values
|
||||
* and scaled to a value between 0 and 1. The value of size can be used to
|
||||
* determine fat touch events.
|
||||
* @param pointer The desired pointer to retrieve. Value may be from 0
|
||||
* (the first pointer) to {@link #getPointerCount()}-1.
|
||||
* @param pointerIndex Raw index of pointer to retrieve. Value may be from 0
|
||||
* (the first pointer that is down) to {@link #getPointerCount()}-1.
|
||||
*/
|
||||
public final float getSize(int pointer) {
|
||||
return mDataSamples[(pointer*NUM_SAMPLE_DATA) + SAMPLE_SIZE];
|
||||
public final float getSize(int pointerIndex) {
|
||||
return mDataSamples[(pointerIndex*NUM_SAMPLE_DATA) + SAMPLE_SIZE];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -758,99 +804,107 @@ public final class MotionEvent implements Parcelable {
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link #getHistoricalX(int)} for the first pointer (pointer 0).
|
||||
* {@link #getHistoricalX(int)} for the first pointer index (may be an
|
||||
* arbitrary pointer identifier).
|
||||
*/
|
||||
public final float getHistoricalX(int pos) {
|
||||
return mDataSamples[((pos + 1) * NUM_SAMPLE_DATA * mNumPointers) + SAMPLE_X];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link #getHistoricalY(int)} for the first pointer (pointer 0).
|
||||
* {@link #getHistoricalY(int)} for the first pointer index (may be an
|
||||
* arbitrary pointer identifier).
|
||||
*/
|
||||
public final float getHistoricalY(int pos) {
|
||||
return mDataSamples[((pos + 1) * NUM_SAMPLE_DATA * mNumPointers) + SAMPLE_Y];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link #getHistoricalPressure(int)} for the first pointer (pointer 0).
|
||||
* {@link #getHistoricalPressure(int)} for the first pointer index (may be an
|
||||
* arbitrary pointer identifier).
|
||||
*/
|
||||
public final float getHistoricalPressure(int pos) {
|
||||
return mDataSamples[((pos + 1) * NUM_SAMPLE_DATA * mNumPointers) + SAMPLE_PRESSURE];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link #getHistoricalSize(int)} for the first pointer (pointer 0).
|
||||
* {@link #getHistoricalSize(int)} for the first pointer index (may be an
|
||||
* arbitrary pointer identifier).
|
||||
*/
|
||||
public final float getHistoricalSize(int pos) {
|
||||
return mDataSamples[((pos + 1) * NUM_SAMPLE_DATA * mNumPointers) + SAMPLE_SIZE];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a historical X coordinate that occurred between this event
|
||||
* and the previous event for the given pointer. Only applies to ACTION_MOVE events.
|
||||
* Returns a historical X coordinate, as per {@link #getX(int)}, that
|
||||
* occurred between this event and the previous event for the given pointer.
|
||||
* Only applies to ACTION_MOVE events.
|
||||
*
|
||||
* @param pointer The desired pointer to retrieve. Value may be from 0
|
||||
* (the first pointer) to {@link #getPointerCount()}-1.
|
||||
* @param pointerIndex Raw index of pointer to retrieve. Value may be from 0
|
||||
* (the first pointer that is down) to {@link #getPointerCount()}-1.
|
||||
* @param pos Which historical value to return; must be less than
|
||||
* {@link #getHistorySize}
|
||||
*
|
||||
* @see #getHistorySize
|
||||
* @see #getX
|
||||
*/
|
||||
public final float getHistoricalX(int pointer, int pos) {
|
||||
public final float getHistoricalX(int pointerIndex, int pos) {
|
||||
return mDataSamples[((pos + 1) * NUM_SAMPLE_DATA * mNumPointers)
|
||||
+ (pointer * NUM_SAMPLE_DATA) + SAMPLE_X];
|
||||
+ (pointerIndex * NUM_SAMPLE_DATA) + SAMPLE_X];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a historical Y coordinate that occurred between this event
|
||||
* and the previous event for the given pointer. Only applies to ACTION_MOVE events.
|
||||
* Returns a historical Y coordinate, as per {@link #getY(int)}, that
|
||||
* occurred between this event and the previous event for the given pointer.
|
||||
* Only applies to ACTION_MOVE events.
|
||||
*
|
||||
* @param pointer The desired pointer to retrieve. Value may be from 0
|
||||
* (the first pointer) to {@link #getPointerCount()}-1.
|
||||
* @param pointerIndex Raw index of pointer to retrieve. Value may be from 0
|
||||
* (the first pointer that is down) to {@link #getPointerCount()}-1.
|
||||
* @param pos Which historical value to return; must be less than
|
||||
* {@link #getHistorySize}
|
||||
*
|
||||
* @see #getHistorySize
|
||||
* @see #getY
|
||||
*/
|
||||
public final float getHistoricalY(int pointer, int pos) {
|
||||
public final float getHistoricalY(int pointerIndex, int pos) {
|
||||
return mDataSamples[((pos + 1) * NUM_SAMPLE_DATA * mNumPointers)
|
||||
+ (pointer * NUM_SAMPLE_DATA) + SAMPLE_Y];
|
||||
+ (pointerIndex * NUM_SAMPLE_DATA) + SAMPLE_Y];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a historical pressure coordinate that occurred between this event
|
||||
* and the previous event for the given pointer. Only applies to ACTION_MOVE events.
|
||||
* Returns a historical pressure coordinate, as per {@link #getPressure(int)},
|
||||
* that occurred between this event and the previous event for the given
|
||||
* pointer. Only applies to ACTION_MOVE events.
|
||||
*
|
||||
* @param pointerIndex Raw index of pointer to retrieve. Value may be from 0
|
||||
* (the first pointer that is down) to {@link #getPointerCount()}-1.
|
||||
* @param pos Which historical value to return; must be less than
|
||||
* {@link #getHistorySize}
|
||||
*
|
||||
* @param pointer The desired pointer to retrieve. Value may be from 0
|
||||
* (the first pointer) to {@link #getPointerCount()}-1.
|
||||
*
|
||||
* @see #getHistorySize
|
||||
* @see #getPressure
|
||||
*/
|
||||
public final float getHistoricalPressure(int pointer, int pos) {
|
||||
public final float getHistoricalPressure(int pointerIndex, int pos) {
|
||||
return mDataSamples[((pos + 1) * NUM_SAMPLE_DATA * mNumPointers)
|
||||
+ (pointer * NUM_SAMPLE_DATA) + SAMPLE_PRESSURE];
|
||||
+ (pointerIndex * NUM_SAMPLE_DATA) + SAMPLE_PRESSURE];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a historical size coordinate that occurred between this event
|
||||
* and the previous event for the given pointer. Only applies to ACTION_MOVE events.
|
||||
* Returns a historical size coordinate, as per {@link #getSize(int)}, that
|
||||
* occurred between this event and the previous event for the given pointer.
|
||||
* Only applies to ACTION_MOVE events.
|
||||
*
|
||||
* @param pointerIndex Raw index of pointer to retrieve. Value may be from 0
|
||||
* (the first pointer that is down) to {@link #getPointerCount()}-1.
|
||||
* @param pos Which historical value to return; must be less than
|
||||
* {@link #getHistorySize}
|
||||
*
|
||||
* @param pointer The desired pointer to retrieve. Value may be from 0
|
||||
* (the first pointer) to {@link #getPointerCount()}-1.
|
||||
*
|
||||
* @see #getHistorySize
|
||||
* @see #getSize
|
||||
*/
|
||||
public final float getHistoricalSize(int pointer, int pos) {
|
||||
public final float getHistoricalSize(int pointerIndex, int pos) {
|
||||
return mDataSamples[((pos + 1) * NUM_SAMPLE_DATA * mNumPointers)
|
||||
+ (pointer * NUM_SAMPLE_DATA) + SAMPLE_SIZE];
|
||||
+ (pointerIndex * NUM_SAMPLE_DATA) + SAMPLE_SIZE];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -938,7 +992,6 @@ public final class MotionEvent implements Parcelable {
|
||||
*/
|
||||
public final void addBatch(long eventTime, float x, float y,
|
||||
float pressure, float size, int metaState) {
|
||||
int[] states = mStateSamples;
|
||||
float[] data = mDataSamples;
|
||||
long[] times = mTimeSamples;
|
||||
|
||||
@@ -946,14 +999,8 @@ public final class MotionEvent implements Parcelable {
|
||||
final int NS = mNumSamples;
|
||||
final int NI = NP*NS;
|
||||
final int ND = NI * NUM_SAMPLE_DATA;
|
||||
if (states.length < (NI+NP)) {
|
||||
// The state and data arrays are sized together, since their
|
||||
// size is always a fixed factor from each other.
|
||||
final int NEW_NI = NP * (NS+BASE_AVAIL_SAMPLES);
|
||||
int[] newState = new int[NEW_NI];
|
||||
System.arraycopy(states, 0, newState, 0, NI);
|
||||
mStateSamples = states = newState;
|
||||
final int NEW_ND = NEW_NI * NUM_SAMPLE_DATA;
|
||||
if (data.length <= ND) {
|
||||
final int NEW_ND = ND + (NP * (BASE_AVAIL_SAMPLES * NUM_SAMPLE_DATA));
|
||||
float[] newData = new float[NEW_ND];
|
||||
System.arraycopy(data, 0, newData, 0, ND);
|
||||
mDataSamples = data = newData;
|
||||
@@ -996,7 +1043,6 @@ public final class MotionEvent implements Parcelable {
|
||||
* @hide
|
||||
*/
|
||||
public final void addBatch(long eventTime, float[] inData, int metaState) {
|
||||
int[] states = mStateSamples;
|
||||
float[] data = mDataSamples;
|
||||
long[] times = mTimeSamples;
|
||||
|
||||
@@ -1004,14 +1050,8 @@ public final class MotionEvent implements Parcelable {
|
||||
final int NS = mNumSamples;
|
||||
final int NI = NP*NS;
|
||||
final int ND = NI * NUM_SAMPLE_DATA;
|
||||
if (states.length < (NI+NP)) {
|
||||
// The state and data arrays are sized together, since their
|
||||
// size is always a fixed factor from each other.
|
||||
final int NEW_NI = NP * (NS+BASE_AVAIL_SAMPLES);
|
||||
int[] newState = new int[NEW_NI];
|
||||
System.arraycopy(states, 0, newState, 0, NI);
|
||||
mStateSamples = states = newState;
|
||||
final int NEW_ND = NEW_NI * NUM_SAMPLE_DATA;
|
||||
if (data.length <= ND) {
|
||||
final int NEW_ND = ND + (NP * (BASE_AVAIL_SAMPLES * NUM_SAMPLE_DATA));
|
||||
float[] newData = new float[NEW_ND];
|
||||
System.arraycopy(data, 0, newData, 0, ND);
|
||||
mDataSamples = data = newData;
|
||||
@@ -1034,6 +1074,21 @@ public final class MotionEvent implements Parcelable {
|
||||
mRawX = inData[SAMPLE_X];
|
||||
mRawY = inData[SAMPLE_Y];
|
||||
mMetaState |= metaState;
|
||||
|
||||
if (DEBUG_POINTERS) {
|
||||
StringBuilder sb = new StringBuilder(128);
|
||||
sb.append("Add:");
|
||||
for (int i=0; i<mNumPointers; i++) {
|
||||
sb.append(" #");
|
||||
sb.append(mPointerIdentifiers[i]);
|
||||
sb.append("(");
|
||||
sb.append(mDataSamples[(i*NUM_SAMPLE_DATA) + SAMPLE_X]);
|
||||
sb.append(",");
|
||||
sb.append(mDataSamples[(i*NUM_SAMPLE_DATA) + SAMPLE_Y]);
|
||||
sb.append(")");
|
||||
}
|
||||
Log.v("MotionEvent", sb.toString());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1074,13 +1129,13 @@ public final class MotionEvent implements Parcelable {
|
||||
final int NI = NP*NS;
|
||||
if (NI > 0) {
|
||||
int i;
|
||||
int[] state = mStateSamples;
|
||||
for (i=0; i<NI; i++) {
|
||||
int[] state = mPointerIdentifiers;
|
||||
for (i=0; i<NP; i++) {
|
||||
out.writeInt(state[i]);
|
||||
}
|
||||
final int NI4 = NI*NUM_SAMPLE_DATA;
|
||||
final int ND = NI*NUM_SAMPLE_DATA;
|
||||
float[] history = mDataSamples;
|
||||
for (i=0; i<NI4; i++) {
|
||||
for (i=0; i<ND; i++) {
|
||||
out.writeFloat(history[i]);
|
||||
}
|
||||
long[] times = mTimeSamples;
|
||||
@@ -1107,19 +1162,19 @@ public final class MotionEvent implements Parcelable {
|
||||
mNumSamples = NS;
|
||||
final int NI = NP*NS;
|
||||
if (NI > 0) {
|
||||
final int NI4 = NI*4;
|
||||
int[] state = mStateSamples;
|
||||
if (state.length < NI) {
|
||||
mStateSamples = state = new int[NI];
|
||||
int[] ids = mPointerIdentifiers;
|
||||
if (ids.length < NP) {
|
||||
mPointerIdentifiers = ids = new int[NP];
|
||||
}
|
||||
for (int i=0; i<NI; i++) {
|
||||
state[i] = in.readInt();
|
||||
for (int i=0; i<NP; i++) {
|
||||
ids[i] = in.readInt();
|
||||
}
|
||||
float[] history = mDataSamples;
|
||||
if (history.length < NI4) {
|
||||
mDataSamples = history = new float[NI4];
|
||||
final int ND = NI*NUM_SAMPLE_DATA;
|
||||
if (history.length < ND) {
|
||||
mDataSamples = history = new float[ND];
|
||||
}
|
||||
for (int i=0; i<NI4; i++) {
|
||||
for (int i=0; i<ND; i++) {
|
||||
history[i] = in.readFloat();
|
||||
}
|
||||
long[] times = mTimeSamples;
|
||||
|
||||
@@ -13,6 +13,8 @@ public class RawInputEvent {
|
||||
public static final int CLASS_ALPHAKEY = 0x00000002;
|
||||
public static final int CLASS_TOUCHSCREEN = 0x00000004;
|
||||
public static final int CLASS_TRACKBALL = 0x00000008;
|
||||
public static final int CLASS_TOUCHSCREEN_MT = 0x00000010;
|
||||
public static final int CLASS_DPAD = 0x00000020;
|
||||
|
||||
// More special classes for QueuedEvent below.
|
||||
public static final int CLASS_CONFIGURATION_CHANGED = 0x10000000;
|
||||
@@ -158,8 +160,21 @@ public class RawInputEvent {
|
||||
public static final int ABS_TOOL_WIDTH = 0x1c;
|
||||
public static final int ABS_VOLUME = 0x20;
|
||||
public static final int ABS_MISC = 0x28;
|
||||
public static final int ABS_MT_TOUCH_MAJOR = 0x30;
|
||||
public static final int ABS_MT_TOUCH_MINOR = 0x31;
|
||||
public static final int ABS_MT_WIDTH_MAJOR = 0x32;
|
||||
public static final int ABS_MT_WIDTH_MINOR = 0x33;
|
||||
public static final int ABS_MT_ORIENTATION = 0x34;
|
||||
public static final int ABS_MT_POSITION_X = 0x35;
|
||||
public static final int ABS_MT_POSITION_Y = 0x36;
|
||||
public static final int ABS_MT_TOOL_TYPE = 0x37;
|
||||
public static final int ABS_MT_BLOB_ID = 0x38;
|
||||
public static final int ABS_MAX = 0x3f;
|
||||
|
||||
public static final int SYN_REPORT = 0;
|
||||
public static final int SYN_CONFIG = 1;
|
||||
public static final int SYN_MT_REPORT = 2;
|
||||
|
||||
public int deviceId;
|
||||
public int type;
|
||||
public int scancode;
|
||||
|
||||
@@ -55,7 +55,9 @@ public:
|
||||
CLASS_KEYBOARD = 0x00000001,
|
||||
CLASS_ALPHAKEY = 0x00000002,
|
||||
CLASS_TOUCHSCREEN = 0x00000004,
|
||||
CLASS_TRACKBALL = 0x00000008
|
||||
CLASS_TRACKBALL = 0x00000008,
|
||||
CLASS_TOUCHSCREEN_MT= 0x00000010,
|
||||
CLASS_DPAD = 0x00000020
|
||||
};
|
||||
uint32_t getDeviceClasses(int32_t deviceId) const;
|
||||
|
||||
@@ -122,6 +124,7 @@ private:
|
||||
};
|
||||
|
||||
device_t* getDevice(int32_t deviceId) const;
|
||||
bool hasKeycode(device_t* device, int keycode) const;
|
||||
|
||||
// Protect all internal state.
|
||||
mutable Mutex mLock;
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
//#define LOG_NDEBUG 0
|
||||
|
||||
#include <ui/EventHub.h>
|
||||
#include <ui/KeycodeLabels.h>
|
||||
#include <hardware_legacy/power.h>
|
||||
|
||||
#include <cutils/properties.h>
|
||||
@@ -58,6 +59,18 @@
|
||||
#define SEQ_SHIFT 16
|
||||
#define id_to_index(id) ((id&ID_MASK)+1)
|
||||
|
||||
#ifndef ABS_MT_TOUCH_MAJOR
|
||||
#define ABS_MT_TOUCH_MAJOR 0x30 /* Major axis of touching ellipse */
|
||||
#endif
|
||||
|
||||
#ifndef ABS_MT_POSITION_X
|
||||
#define ABS_MT_POSITION_X 0x35 /* Center X ellipse position */
|
||||
#endif
|
||||
|
||||
#ifndef ABS_MT_POSITION_Y
|
||||
#define ABS_MT_POSITION_Y 0x36 /* Center Y ellipse position */
|
||||
#endif
|
||||
|
||||
namespace android {
|
||||
|
||||
static const char *WAKE_LOCK_ID = "KeyEvents";
|
||||
@@ -590,6 +603,8 @@ int EventHub::open_device(const char *deviceName)
|
||||
mFDs[mFDCount].events = POLLIN;
|
||||
|
||||
// figure out the kinds of events the device reports
|
||||
|
||||
// See if this is a keyboard, and classify it.
|
||||
uint8_t key_bitmask[(KEY_MAX+1)/8];
|
||||
memset(key_bitmask, 0, sizeof(key_bitmask));
|
||||
LOGV("Getting keys...");
|
||||
@@ -601,15 +616,11 @@ int EventHub::open_device(const char *deviceName)
|
||||
for (int i=0; i<((BTN_MISC+7)/8); i++) {
|
||||
if (key_bitmask[i] != 0) {
|
||||
device->classes |= CLASS_KEYBOARD;
|
||||
// 'Q' key support = cheap test of whether this is an alpha-capable kbd
|
||||
if (test_bit(KEY_Q, key_bitmask)) {
|
||||
device->classes |= CLASS_ALPHAKEY;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ((device->classes & CLASS_KEYBOARD) != 0) {
|
||||
device->keyBitmask = new uint8_t[(KEY_MAX+1)/8];
|
||||
device->keyBitmask = new uint8_t[sizeof(key_bitmask)];
|
||||
if (device->keyBitmask != NULL) {
|
||||
memcpy(device->keyBitmask, key_bitmask, sizeof(key_bitmask));
|
||||
} else {
|
||||
@@ -619,6 +630,8 @@ int EventHub::open_device(const char *deviceName)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// See if this is a trackball.
|
||||
if (test_bit(BTN_MOUSE, key_bitmask)) {
|
||||
uint8_t rel_bitmask[(REL_MAX+1)/8];
|
||||
memset(rel_bitmask, 0, sizeof(rel_bitmask));
|
||||
@@ -630,16 +643,22 @@ int EventHub::open_device(const char *deviceName)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (test_bit(BTN_TOUCH, key_bitmask)) {
|
||||
uint8_t abs_bitmask[(ABS_MAX+1)/8];
|
||||
memset(abs_bitmask, 0, sizeof(abs_bitmask));
|
||||
LOGV("Getting absolute controllers...");
|
||||
if (ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(abs_bitmask)), abs_bitmask) >= 0)
|
||||
{
|
||||
if (test_bit(ABS_X, abs_bitmask) && test_bit(ABS_Y, abs_bitmask)) {
|
||||
device->classes |= CLASS_TOUCHSCREEN;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t abs_bitmask[(ABS_MAX+1)/8];
|
||||
memset(abs_bitmask, 0, sizeof(abs_bitmask));
|
||||
LOGV("Getting absolute controllers...");
|
||||
ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(abs_bitmask)), abs_bitmask);
|
||||
|
||||
// Is this a new modern multi-touch driver?
|
||||
if (test_bit(ABS_MT_TOUCH_MAJOR, abs_bitmask)
|
||||
&& test_bit(ABS_MT_POSITION_X, abs_bitmask)
|
||||
&& test_bit(ABS_MT_POSITION_Y, abs_bitmask)) {
|
||||
device->classes |= CLASS_TOUCHSCREEN | CLASS_TOUCHSCREEN_MT;
|
||||
|
||||
// Is this an old style single-touch driver?
|
||||
} else if (test_bit(BTN_TOUCH, key_bitmask)
|
||||
&& test_bit(ABS_X, abs_bitmask) && test_bit(ABS_Y, abs_bitmask)) {
|
||||
device->classes |= CLASS_TOUCHSCREEN;
|
||||
}
|
||||
|
||||
#ifdef EV_SW
|
||||
@@ -658,9 +677,6 @@ int EventHub::open_device(const char *deviceName)
|
||||
}
|
||||
#endif
|
||||
|
||||
LOGI("New device: path=%s name=%s id=0x%x (of 0x%x) index=%d fd=%d classes=0x%x\n",
|
||||
deviceName, name, device->id, mNumDevicesById, mFDCount, fd, device->classes);
|
||||
|
||||
if ((device->classes&CLASS_KEYBOARD) != 0) {
|
||||
char devname[101];
|
||||
char tmpfn[101];
|
||||
@@ -707,10 +723,27 @@ int EventHub::open_device(const char *deviceName)
|
||||
sprintf(propName, "hw.keyboards.%u.devname", publicID);
|
||||
property_set(propName, devname);
|
||||
|
||||
LOGI("New keyboard: publicID=%d device->id=%d devname='%s' propName='%s' keylayout='%s'\n",
|
||||
// 'Q' key support = cheap test of whether this is an alpha-capable kbd
|
||||
if (hasKeycode(device, kKeyCodeQ)) {
|
||||
device->classes |= CLASS_ALPHAKEY;
|
||||
}
|
||||
|
||||
// See if this has a DPAD.
|
||||
if (hasKeycode(device, kKeyCodeDpadUp) &&
|
||||
hasKeycode(device, kKeyCodeDpadDown) &&
|
||||
hasKeycode(device, kKeyCodeDpadLeft) &&
|
||||
hasKeycode(device, kKeyCodeDpadRight) &&
|
||||
hasKeycode(device, kKeyCodeDpadCenter)) {
|
||||
device->classes |= CLASS_DPAD;
|
||||
}
|
||||
|
||||
LOGI("New keyboard: publicID=%d device->id=0x%x devname='%s' propName='%s' keylayout='%s'\n",
|
||||
publicID, device->id, devname, propName, keylayoutFilename);
|
||||
}
|
||||
|
||||
LOGI("New device: path=%s name=%s id=0x%x (of 0x%x) index=%d fd=%d classes=0x%x\n",
|
||||
deviceName, name, device->id, mNumDevicesById, mFDCount, fd, device->classes);
|
||||
|
||||
LOGV("Adding device %s %p at %d, id = %d, classes = 0x%x\n",
|
||||
deviceName, device, mFDCount, devid, device->classes);
|
||||
|
||||
@@ -723,6 +756,25 @@ int EventHub::open_device(const char *deviceName)
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool EventHub::hasKeycode(device_t* device, int keycode) const
|
||||
{
|
||||
if (device->keyBitmask == NULL || device->layoutMap == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Vector<int32_t> scanCodes;
|
||||
device->layoutMap->findScancodes(keycode, &scanCodes);
|
||||
const size_t N = scanCodes.size();
|
||||
for (size_t i=0; i<N && i<=KEY_MAX; i++) {
|
||||
int32_t sc = scanCodes.itemAt(i);
|
||||
if (sc >= 0 && sc <= KEY_MAX && test_bit(sc, device->keyBitmask)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int EventHub::close_device(const char *deviceName)
|
||||
{
|
||||
AutoMutex _l(mLock);
|
||||
|
||||
@@ -23,11 +23,13 @@ import android.view.Surface;
|
||||
import android.view.WindowManagerPolicy;
|
||||
|
||||
public class InputDevice {
|
||||
static final boolean DEBUG_POINTERS = false;
|
||||
|
||||
/** Amount that trackball needs to move in order to generate a key event. */
|
||||
static final int TRACKBALL_MOVEMENT_THRESHOLD = 6;
|
||||
|
||||
/** Maximum number of pointers we will track and report. */
|
||||
static final int MAX_POINTERS = 2;
|
||||
static final int MAX_POINTERS = 10;
|
||||
|
||||
final int id;
|
||||
final int classes;
|
||||
@@ -51,100 +53,316 @@ public class InputDevice {
|
||||
float yMoveScale;
|
||||
MotionEvent currentMove = null;
|
||||
boolean changed = false;
|
||||
boolean mLastAnyDown = false;
|
||||
long mDownTime = 0;
|
||||
final boolean[] mLastDown = new boolean[MAX_POINTERS];
|
||||
final boolean[] mDown = new boolean[MAX_POINTERS];
|
||||
|
||||
// The currently assigned pointer IDs, corresponding to the last data.
|
||||
int[] mPointerIds = new int[MAX_POINTERS];
|
||||
|
||||
// This is the last generated pointer data, ordered to match
|
||||
// mPointerIds.
|
||||
int mLastNumPointers = 0;
|
||||
final int[] mLastData = new int[MotionEvent.NUM_SAMPLE_DATA * MAX_POINTERS];
|
||||
final int[] mCurData = new int[MotionEvent.NUM_SAMPLE_DATA * MAX_POINTERS];
|
||||
|
||||
// This is the next set of pointer data being generated. It is not
|
||||
// in any known order, and will be propagated in to mLastData
|
||||
// as part of mapping it to the appropriate pointer IDs.
|
||||
// Note that we have one extra sample of data here, to help clients
|
||||
// avoid doing bounds checking.
|
||||
int mNextNumPointers = 0;
|
||||
final int[] mNextData = new int[(MotionEvent.NUM_SAMPLE_DATA * MAX_POINTERS)
|
||||
+ MotionEvent.NUM_SAMPLE_DATA];
|
||||
|
||||
// Temporary data structures for doing the pointer ID mapping.
|
||||
final int[] mLast2Next = new int[MAX_POINTERS];
|
||||
final int[] mNext2Last = new int[MAX_POINTERS];
|
||||
final long[] mNext2LastDistance = new long[MAX_POINTERS];
|
||||
|
||||
// Temporary data structure for generating the final motion data.
|
||||
final float[] mReportData = new float[MotionEvent.NUM_SAMPLE_DATA * MAX_POINTERS];
|
||||
|
||||
// This is not used here, but can be used by callers for state tracking.
|
||||
int mAddingPointerOffset = 0;
|
||||
final boolean[] mDown = new boolean[MAX_POINTERS];
|
||||
|
||||
MotionState(int mx, int my) {
|
||||
xPrecision = mx;
|
||||
yPrecision = my;
|
||||
xMoveScale = mx != 0 ? (1.0f/mx) : 1.0f;
|
||||
yMoveScale = my != 0 ? (1.0f/my) : 1.0f;
|
||||
for (int i=0; i<MAX_POINTERS; i++) {
|
||||
mPointerIds[i] = i;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean assignPointer(int nextIndex, boolean allowOverlap) {
|
||||
final int lastNumPointers = mLastNumPointers;
|
||||
final int[] next2Last = mNext2Last;
|
||||
final long[] next2LastDistance = mNext2LastDistance;
|
||||
final int[] last2Next = mLast2Next;
|
||||
final int[] lastData = mLastData;
|
||||
final int[] nextData = mNextData;
|
||||
final int id = nextIndex * MotionEvent.NUM_SAMPLE_DATA;
|
||||
|
||||
if (DEBUG_POINTERS) Log.v("InputDevice", "assignPointer: nextIndex="
|
||||
+ nextIndex + " dataOff=" + id);
|
||||
final int x1 = nextData[id + MotionEvent.SAMPLE_X];
|
||||
final int y1 = nextData[id + MotionEvent.SAMPLE_Y];
|
||||
|
||||
long bestDistance = -1;
|
||||
int bestIndex = -1;
|
||||
for (int j=0; j<lastNumPointers; j++) {
|
||||
if (!allowOverlap && last2Next[j] < 0) {
|
||||
continue;
|
||||
}
|
||||
final int jd = j * MotionEvent.NUM_SAMPLE_DATA;
|
||||
final int xd = lastData[jd + MotionEvent.SAMPLE_X] - x1;
|
||||
final int yd = lastData[jd + MotionEvent.SAMPLE_Y] - y1;
|
||||
final long distance = xd*(long)xd + yd*(long)yd;
|
||||
if (j == 0 || distance < bestDistance) {
|
||||
bestDistance = distance;
|
||||
bestIndex = j;
|
||||
}
|
||||
}
|
||||
|
||||
if (DEBUG_POINTERS) Log.v("InputDevice", "New index " + nextIndex
|
||||
+ " best old index=" + bestIndex + " (distance="
|
||||
+ bestDistance + ")");
|
||||
next2Last[nextIndex] = bestIndex;
|
||||
next2LastDistance[nextIndex] = bestDistance;
|
||||
|
||||
if (bestIndex < 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (last2Next[bestIndex] == -1) {
|
||||
last2Next[bestIndex] = nextIndex;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (DEBUG_POINTERS) Log.v("InputDevice", "Old index " + bestIndex
|
||||
+ " has multiple best new pointers!");
|
||||
|
||||
last2Next[bestIndex] = -2;
|
||||
return true;
|
||||
}
|
||||
|
||||
private int updatePointerIdentifiers() {
|
||||
final int[] lastData = mLastData;
|
||||
final int[] nextData = mNextData;
|
||||
final int nextNumPointers = mNextNumPointers;
|
||||
final int lastNumPointers = mLastNumPointers;
|
||||
|
||||
if (nextNumPointers == 1 && lastNumPointers == 1) {
|
||||
System.arraycopy(nextData, 0, lastData, 0,
|
||||
MotionEvent.NUM_SAMPLE_DATA);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Clear our old state.
|
||||
final int[] last2Next = mLast2Next;
|
||||
for (int i=0; i<lastNumPointers; i++) {
|
||||
last2Next[i] = -1;
|
||||
}
|
||||
|
||||
if (DEBUG_POINTERS) Log.v("InputDevice",
|
||||
"Update pointers: lastNumPointers=" + lastNumPointers
|
||||
+ " nextNumPointers=" + nextNumPointers);
|
||||
|
||||
// Figure out the closes new points to the previous points.
|
||||
final int[] next2Last = mNext2Last;
|
||||
final long[] next2LastDistance = mNext2LastDistance;
|
||||
boolean conflicts = false;
|
||||
for (int i=0; i<nextNumPointers; i++) {
|
||||
conflicts |= assignPointer(i, true);
|
||||
}
|
||||
|
||||
// Resolve ambiguities in pointer mappings, when two or more
|
||||
// new pointer locations find their best previous location is
|
||||
// the same.
|
||||
if (conflicts) {
|
||||
if (DEBUG_POINTERS) Log.v("InputDevice", "Resolving conflicts");
|
||||
|
||||
for (int i=0; i<lastNumPointers; i++) {
|
||||
if (last2Next[i] != -2) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Note that this algorithm is far from perfect. Ideally
|
||||
// we should do something like the one described at
|
||||
// http://portal.acm.org/citation.cfm?id=997856
|
||||
|
||||
if (DEBUG_POINTERS) Log.v("InputDevice",
|
||||
"Resolving last index #" + i);
|
||||
|
||||
int numFound;
|
||||
do {
|
||||
numFound = 0;
|
||||
long worstDistance = 0;
|
||||
int worstJ = -1;
|
||||
for (int j=0; j<nextNumPointers; j++) {
|
||||
if (next2Last[j] != i) {
|
||||
continue;
|
||||
}
|
||||
numFound++;
|
||||
if (worstDistance < next2LastDistance[j]) {
|
||||
worstDistance = next2LastDistance[j];
|
||||
worstJ = j;
|
||||
}
|
||||
}
|
||||
|
||||
if (worstJ >= 0) {
|
||||
if (DEBUG_POINTERS) Log.v("InputDevice",
|
||||
"Worst new pointer: " + worstJ
|
||||
+ " (distance=" + worstDistance + ")");
|
||||
if (assignPointer(worstJ, false)) {
|
||||
// In this case there is no last pointer
|
||||
// remaining for this new one!
|
||||
next2Last[worstJ] = -1;
|
||||
}
|
||||
}
|
||||
} while (numFound > 2);
|
||||
}
|
||||
}
|
||||
|
||||
int retIndex = -1;
|
||||
|
||||
if (lastNumPointers < nextNumPointers) {
|
||||
// We have one or more new pointers that are down. Create a
|
||||
// new pointer identifier for one of them.
|
||||
if (DEBUG_POINTERS) Log.v("InputDevice", "Adding new pointer");
|
||||
int nextId = 0;
|
||||
int i=0;
|
||||
while (i < lastNumPointers) {
|
||||
if (mPointerIds[i] > nextId) {
|
||||
// Found a hole, insert the pointer here.
|
||||
if (DEBUG_POINTERS) Log.v("InputDevice",
|
||||
"Inserting new pointer at hole " + i);
|
||||
System.arraycopy(mPointerIds, i, mPointerIds,
|
||||
i+1, lastNumPointers-i);
|
||||
System.arraycopy(lastData, i*MotionEvent.NUM_SAMPLE_DATA,
|
||||
lastData, (i+1)*MotionEvent.NUM_SAMPLE_DATA,
|
||||
(lastNumPointers-i)*MotionEvent.NUM_SAMPLE_DATA);
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
nextId++;
|
||||
}
|
||||
|
||||
if (DEBUG_POINTERS) Log.v("InputDevice",
|
||||
"New pointer id " + nextId + " at index " + i);
|
||||
|
||||
mLastNumPointers++;
|
||||
retIndex = i;
|
||||
mPointerIds[i] = nextId;
|
||||
|
||||
// And assign this identifier to the first new pointer.
|
||||
for (int j=0; j<nextNumPointers; j++) {
|
||||
if (next2Last[j] < 0) {
|
||||
if (DEBUG_POINTERS) Log.v("InputDevice",
|
||||
"Assigning new id to new pointer index " + j);
|
||||
next2Last[j] = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Propagate all of the current data into the appropriate
|
||||
// location in the old data to match the pointer ID that was
|
||||
// assigned to it.
|
||||
for (int i=0; i<nextNumPointers; i++) {
|
||||
int lastIndex = next2Last[i];
|
||||
if (lastIndex >= 0) {
|
||||
if (DEBUG_POINTERS) Log.v("InputDevice",
|
||||
"Copying next pointer index " + i
|
||||
+ " to last index " + lastIndex);
|
||||
System.arraycopy(nextData, i*MotionEvent.NUM_SAMPLE_DATA,
|
||||
lastData, lastIndex*MotionEvent.NUM_SAMPLE_DATA,
|
||||
MotionEvent.NUM_SAMPLE_DATA);
|
||||
}
|
||||
}
|
||||
|
||||
if (lastNumPointers > nextNumPointers) {
|
||||
// One or more pointers has gone up. Find the first one,
|
||||
// and adjust accordingly.
|
||||
if (DEBUG_POINTERS) Log.v("InputDevice", "Removing old pointer");
|
||||
for (int i=0; i<lastNumPointers; i++) {
|
||||
if (last2Next[i] == -1) {
|
||||
if (DEBUG_POINTERS) Log.v("InputDevice",
|
||||
"Removing old pointer at index " + i);
|
||||
retIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return retIndex;
|
||||
}
|
||||
|
||||
void removeOldPointer(int index) {
|
||||
final int lastNumPointers = mLastNumPointers;
|
||||
if (index >= 0 && index < lastNumPointers) {
|
||||
System.arraycopy(mPointerIds, index+1, mPointerIds,
|
||||
index, lastNumPointers-index-1);
|
||||
System.arraycopy(mLastData, (index+1)*MotionEvent.NUM_SAMPLE_DATA,
|
||||
mLastData, (index)*MotionEvent.NUM_SAMPLE_DATA,
|
||||
(lastNumPointers-index-1)*MotionEvent.NUM_SAMPLE_DATA);
|
||||
mLastNumPointers--;
|
||||
}
|
||||
}
|
||||
|
||||
MotionEvent generateAbsMotion(InputDevice device, long curTime,
|
||||
long curTimeNano, Display display, int orientation,
|
||||
int metaState) {
|
||||
|
||||
final float[] scaled = mReportData;
|
||||
final int[] cur = mCurData;
|
||||
|
||||
boolean anyDown = false;
|
||||
int firstDownChanged = -1;
|
||||
int numPointers = 0;
|
||||
for (int i=0; i<MAX_POINTERS; i++) {
|
||||
boolean d = mDown[i];
|
||||
anyDown |= d;
|
||||
if (d != mLastDown[i] && firstDownChanged < 0) {
|
||||
firstDownChanged = i;
|
||||
mLastDown[i] = mDown[i];
|
||||
d = true;
|
||||
}
|
||||
|
||||
if (d) {
|
||||
final int src = i * MotionEvent.NUM_SAMPLE_DATA;
|
||||
final int dest = numPointers * MotionEvent.NUM_SAMPLE_DATA;
|
||||
numPointers++;
|
||||
scaled[dest + MotionEvent.SAMPLE_X] = cur[src + MotionEvent.SAMPLE_X];
|
||||
scaled[dest + MotionEvent.SAMPLE_Y] = cur[src + MotionEvent.SAMPLE_Y];
|
||||
scaled[dest + MotionEvent.SAMPLE_PRESSURE] = cur[src + MotionEvent.SAMPLE_PRESSURE];
|
||||
scaled[dest + MotionEvent.SAMPLE_SIZE] = cur[src + MotionEvent.SAMPLE_SIZE];
|
||||
}
|
||||
if (mNextNumPointers <= 0 && mLastNumPointers <= 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (numPointers <= 0) {
|
||||
return null;
|
||||
final int lastNumPointers = mLastNumPointers;
|
||||
final int nextNumPointers = mNextNumPointers;
|
||||
if (mNextNumPointers > MAX_POINTERS) {
|
||||
Log.w("InputDevice", "Number of pointers " + mNextNumPointers
|
||||
+ " exceeded maximum of " + MAX_POINTERS);
|
||||
mNextNumPointers = MAX_POINTERS;
|
||||
}
|
||||
|
||||
int upOrDownPointer = updatePointerIdentifiers();
|
||||
|
||||
final float[] reportData = mReportData;
|
||||
final int[] rawData = mLastData;
|
||||
|
||||
final int numPointers = mLastNumPointers;
|
||||
|
||||
if (DEBUG_POINTERS) Log.v("InputDevice", "Processing "
|
||||
+ numPointers + " pointers (going from " + lastNumPointers
|
||||
+ " to " + nextNumPointers + ")");
|
||||
|
||||
for (int i=0; i<numPointers; i++) {
|
||||
final int pos = i * MotionEvent.NUM_SAMPLE_DATA;
|
||||
reportData[pos + MotionEvent.SAMPLE_X] = rawData[pos + MotionEvent.SAMPLE_X];
|
||||
reportData[pos + MotionEvent.SAMPLE_Y] = rawData[pos + MotionEvent.SAMPLE_Y];
|
||||
reportData[pos + MotionEvent.SAMPLE_PRESSURE] = rawData[pos + MotionEvent.SAMPLE_PRESSURE];
|
||||
reportData[pos + MotionEvent.SAMPLE_SIZE] = rawData[pos + MotionEvent.SAMPLE_SIZE];
|
||||
}
|
||||
|
||||
int action;
|
||||
int edgeFlags = 0;
|
||||
if (anyDown != mLastAnyDown) {
|
||||
final AbsoluteInfo absX = device.absX;
|
||||
final AbsoluteInfo absY = device.absY;
|
||||
if (anyDown && absX != null && absY != null) {
|
||||
// We don't let downs start unless we are
|
||||
// inside of the screen. There are two reasons for
|
||||
// this: to avoid spurious touches when holding
|
||||
// the edges of the device near the touchscreen,
|
||||
// and to avoid reporting events if there are virtual
|
||||
// keys on the touchscreen outside of the display
|
||||
// area.
|
||||
// Note that we are only looking at the first pointer,
|
||||
// since what we are handling here is the first pointer
|
||||
// going down, and this is the coordinate that will be
|
||||
// used to dispatch the event.
|
||||
if (cur[MotionEvent.SAMPLE_X] < absX.minValue
|
||||
|| cur[MotionEvent.SAMPLE_X] > absX.maxValue
|
||||
|| cur[MotionEvent.SAMPLE_Y] < absY.minValue
|
||||
|| cur[MotionEvent.SAMPLE_Y] > absY.maxValue) {
|
||||
if (false) Log.v("InputDevice", "Rejecting ("
|
||||
+ cur[MotionEvent.SAMPLE_X] + ","
|
||||
+ cur[MotionEvent.SAMPLE_Y] + "): outside of ("
|
||||
+ absX.minValue + "," + absY.minValue
|
||||
+ ")-(" + absX.maxValue + ","
|
||||
+ absY.maxValue + ")");
|
||||
return null;
|
||||
if (nextNumPointers != lastNumPointers) {
|
||||
if (nextNumPointers > lastNumPointers) {
|
||||
if (lastNumPointers == 0) {
|
||||
action = MotionEvent.ACTION_DOWN;
|
||||
mDownTime = curTime;
|
||||
} else {
|
||||
action = MotionEvent.ACTION_POINTER_DOWN
|
||||
| (upOrDownPointer << MotionEvent.ACTION_POINTER_ID_SHIFT);
|
||||
}
|
||||
}
|
||||
mLastAnyDown = anyDown;
|
||||
if (anyDown) {
|
||||
action = MotionEvent.ACTION_DOWN;
|
||||
mDownTime = curTime;
|
||||
} else {
|
||||
action = MotionEvent.ACTION_UP;
|
||||
}
|
||||
currentMove = null;
|
||||
} else if (firstDownChanged >= 0) {
|
||||
if (mDown[firstDownChanged]) {
|
||||
action = MotionEvent.ACTION_POINTER_DOWN
|
||||
| (firstDownChanged << MotionEvent.ACTION_POINTER_SHIFT);
|
||||
} else {
|
||||
action = MotionEvent.ACTION_POINTER_UP
|
||||
| (firstDownChanged << MotionEvent.ACTION_POINTER_SHIFT);
|
||||
if (numPointers == 1) {
|
||||
action = MotionEvent.ACTION_UP;
|
||||
} else {
|
||||
action = MotionEvent.ACTION_POINTER_UP
|
||||
| (upOrDownPointer << MotionEvent.ACTION_POINTER_ID_SHIFT);
|
||||
}
|
||||
}
|
||||
currentMove = null;
|
||||
} else {
|
||||
@@ -170,42 +388,42 @@ public class InputDevice {
|
||||
final int j = i * MotionEvent.NUM_SAMPLE_DATA;
|
||||
|
||||
if (absX != null) {
|
||||
scaled[j + MotionEvent.SAMPLE_X] =
|
||||
((scaled[j + MotionEvent.SAMPLE_X]-absX.minValue)
|
||||
reportData[j + MotionEvent.SAMPLE_X] =
|
||||
((reportData[j + MotionEvent.SAMPLE_X]-absX.minValue)
|
||||
/ absX.range) * w;
|
||||
}
|
||||
if (absY != null) {
|
||||
scaled[j + MotionEvent.SAMPLE_Y] =
|
||||
((scaled[j + MotionEvent.SAMPLE_Y]-absY.minValue)
|
||||
reportData[j + MotionEvent.SAMPLE_Y] =
|
||||
((reportData[j + MotionEvent.SAMPLE_Y]-absY.minValue)
|
||||
/ absY.range) * h;
|
||||
}
|
||||
if (absPressure != null) {
|
||||
scaled[j + MotionEvent.SAMPLE_PRESSURE] =
|
||||
((scaled[j + MotionEvent.SAMPLE_PRESSURE]-absPressure.minValue)
|
||||
reportData[j + MotionEvent.SAMPLE_PRESSURE] =
|
||||
((reportData[j + MotionEvent.SAMPLE_PRESSURE]-absPressure.minValue)
|
||||
/ (float)absPressure.range);
|
||||
}
|
||||
if (absSize != null) {
|
||||
scaled[j + MotionEvent.SAMPLE_SIZE] =
|
||||
((scaled[j + MotionEvent.SAMPLE_SIZE]-absSize.minValue)
|
||||
reportData[j + MotionEvent.SAMPLE_SIZE] =
|
||||
((reportData[j + MotionEvent.SAMPLE_SIZE]-absSize.minValue)
|
||||
/ (float)absSize.range);
|
||||
}
|
||||
|
||||
switch (orientation) {
|
||||
case Surface.ROTATION_90: {
|
||||
final float temp = scaled[MotionEvent.SAMPLE_X];
|
||||
scaled[j + MotionEvent.SAMPLE_X] = scaled[j + MotionEvent.SAMPLE_Y];
|
||||
scaled[j + MotionEvent.SAMPLE_Y] = w-temp;
|
||||
final float temp = reportData[MotionEvent.SAMPLE_X];
|
||||
reportData[j + MotionEvent.SAMPLE_X] = reportData[j + MotionEvent.SAMPLE_Y];
|
||||
reportData[j + MotionEvent.SAMPLE_Y] = w-temp;
|
||||
break;
|
||||
}
|
||||
case Surface.ROTATION_180: {
|
||||
scaled[j + MotionEvent.SAMPLE_X] = w-scaled[j + MotionEvent.SAMPLE_X];
|
||||
scaled[j + MotionEvent.SAMPLE_Y] = h-scaled[j + MotionEvent.SAMPLE_Y];
|
||||
reportData[j + MotionEvent.SAMPLE_X] = w-reportData[j + MotionEvent.SAMPLE_X];
|
||||
reportData[j + MotionEvent.SAMPLE_Y] = h-reportData[j + MotionEvent.SAMPLE_Y];
|
||||
break;
|
||||
}
|
||||
case Surface.ROTATION_270: {
|
||||
final float temp = scaled[i + MotionEvent.SAMPLE_X];
|
||||
scaled[j + MotionEvent.SAMPLE_X] = h-scaled[j + MotionEvent.SAMPLE_Y];
|
||||
scaled[j + MotionEvent.SAMPLE_Y] = temp;
|
||||
final float temp = reportData[i + MotionEvent.SAMPLE_X];
|
||||
reportData[j + MotionEvent.SAMPLE_X] = h-reportData[j + MotionEvent.SAMPLE_Y];
|
||||
reportData[j + MotionEvent.SAMPLE_Y] = temp;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -214,24 +432,24 @@ public class InputDevice {
|
||||
// We only consider the first pointer when computing the edge
|
||||
// flags, since they are global to the event.
|
||||
if (action == MotionEvent.ACTION_DOWN) {
|
||||
if (scaled[MotionEvent.SAMPLE_X] <= 0) {
|
||||
if (reportData[MotionEvent.SAMPLE_X] <= 0) {
|
||||
edgeFlags |= MotionEvent.EDGE_LEFT;
|
||||
} else if (scaled[MotionEvent.SAMPLE_X] >= dispW) {
|
||||
} else if (reportData[MotionEvent.SAMPLE_X] >= dispW) {
|
||||
edgeFlags |= MotionEvent.EDGE_RIGHT;
|
||||
}
|
||||
if (scaled[MotionEvent.SAMPLE_Y] <= 0) {
|
||||
if (reportData[MotionEvent.SAMPLE_Y] <= 0) {
|
||||
edgeFlags |= MotionEvent.EDGE_TOP;
|
||||
} else if (scaled[MotionEvent.SAMPLE_Y] >= dispH) {
|
||||
} else if (reportData[MotionEvent.SAMPLE_Y] >= dispH) {
|
||||
edgeFlags |= MotionEvent.EDGE_BOTTOM;
|
||||
}
|
||||
}
|
||||
|
||||
if (currentMove != null) {
|
||||
if (false) Log.i("InputDevice", "Adding batch x="
|
||||
+ scaled[MotionEvent.SAMPLE_X]
|
||||
+ " y=" + scaled[MotionEvent.SAMPLE_Y]
|
||||
+ reportData[MotionEvent.SAMPLE_X]
|
||||
+ " y=" + reportData[MotionEvent.SAMPLE_Y]
|
||||
+ " to " + currentMove);
|
||||
currentMove.addBatch(curTime, scaled, metaState);
|
||||
currentMove.addBatch(curTime, reportData, metaState);
|
||||
if (WindowManagerPolicy.WATCH_POINTER) {
|
||||
Log.i("KeyInputQueue", "Updating: " + currentMove);
|
||||
}
|
||||
@@ -239,37 +457,53 @@ public class InputDevice {
|
||||
}
|
||||
|
||||
MotionEvent me = MotionEvent.obtainNano(mDownTime, curTime,
|
||||
curTimeNano, action, numPointers, scaled, metaState,
|
||||
xPrecision, yPrecision, device.id, edgeFlags);
|
||||
curTimeNano, action, numPointers, mPointerIds, reportData,
|
||||
metaState, xPrecision, yPrecision, device.id, edgeFlags);
|
||||
if (action == MotionEvent.ACTION_MOVE) {
|
||||
currentMove = me;
|
||||
}
|
||||
|
||||
if (nextNumPointers < lastNumPointers) {
|
||||
removeOldPointer(upOrDownPointer);
|
||||
}
|
||||
|
||||
return me;
|
||||
}
|
||||
|
||||
boolean hasMore() {
|
||||
return mLastNumPointers != mNextNumPointers;
|
||||
}
|
||||
|
||||
void finish() {
|
||||
mNextNumPointers = mAddingPointerOffset = 0;
|
||||
mNextData[MotionEvent.SAMPLE_PRESSURE] = 0;
|
||||
}
|
||||
|
||||
MotionEvent generateRelMotion(InputDevice device, long curTime,
|
||||
long curTimeNano, int orientation, int metaState) {
|
||||
|
||||
final float[] scaled = mReportData;
|
||||
|
||||
// For now we only support 1 pointer with relative motions.
|
||||
scaled[MotionEvent.SAMPLE_X] = mCurData[MotionEvent.SAMPLE_X];
|
||||
scaled[MotionEvent.SAMPLE_Y] = mCurData[MotionEvent.SAMPLE_Y];
|
||||
scaled[MotionEvent.SAMPLE_X] = mNextData[MotionEvent.SAMPLE_X];
|
||||
scaled[MotionEvent.SAMPLE_Y] = mNextData[MotionEvent.SAMPLE_Y];
|
||||
scaled[MotionEvent.SAMPLE_PRESSURE] = 1.0f;
|
||||
scaled[MotionEvent.SAMPLE_SIZE] = 0;
|
||||
int edgeFlags = 0;
|
||||
|
||||
int action;
|
||||
if (mDown[0] != mLastDown[0]) {
|
||||
mCurData[MotionEvent.SAMPLE_X] =
|
||||
mCurData[MotionEvent.SAMPLE_Y] = 0;
|
||||
mLastDown[0] = mDown[0];
|
||||
if (mDown[0]) {
|
||||
if (mNextNumPointers != mLastNumPointers) {
|
||||
mNextData[MotionEvent.SAMPLE_X] =
|
||||
mNextData[MotionEvent.SAMPLE_Y] = 0;
|
||||
if (mNextNumPointers > 0 && mLastNumPointers == 0) {
|
||||
action = MotionEvent.ACTION_DOWN;
|
||||
mDownTime = curTime;
|
||||
} else {
|
||||
} else if (mNextNumPointers == 0) {
|
||||
action = MotionEvent.ACTION_UP;
|
||||
} else {
|
||||
action = MotionEvent.ACTION_MOVE;
|
||||
}
|
||||
mLastNumPointers = mNextNumPointers;
|
||||
currentMove = null;
|
||||
} else {
|
||||
action = MotionEvent.ACTION_MOVE;
|
||||
@@ -310,7 +544,7 @@ public class InputDevice {
|
||||
}
|
||||
|
||||
MotionEvent me = MotionEvent.obtainNano(mDownTime, curTime,
|
||||
curTimeNano, action, 1, scaled, metaState,
|
||||
curTimeNano, action, 1, mPointerIds, scaled, metaState,
|
||||
xPrecision, yPrecision, device.id, edgeFlags);
|
||||
if (action == MotionEvent.ACTION_MOVE) {
|
||||
currentMove = me;
|
||||
|
||||
@@ -49,6 +49,7 @@ public abstract class KeyInputQueue {
|
||||
static final String TAG = "KeyInputQueue";
|
||||
|
||||
static final boolean DEBUG_VIRTUAL_KEYS = false;
|
||||
static final boolean DEBUG_POINTERS = false;
|
||||
|
||||
private static final String EXCLUDED_DEVICES_PATH = "etc/excluded-input-devices.xml";
|
||||
|
||||
@@ -326,6 +327,10 @@ public abstract class KeyInputQueue {
|
||||
config.navigation
|
||||
= Configuration.NAVIGATION_TRACKBALL;
|
||||
//Log.i("foo", "***** HAVE TRACKBALL!");
|
||||
} else if ((d.classes&RawInputEvent.CLASS_DPAD) != 0) {
|
||||
config.navigation
|
||||
= Configuration.NAVIGATION_DPAD;
|
||||
//Log.i("foo", "***** HAVE DPAD!");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -364,9 +369,9 @@ public abstract class KeyInputQueue {
|
||||
android.os.Process.setThreadPriority(
|
||||
android.os.Process.THREAD_PRIORITY_URGENT_DISPLAY);
|
||||
|
||||
try {
|
||||
RawInputEvent ev = new RawInputEvent();
|
||||
while (true) {
|
||||
RawInputEvent ev = new RawInputEvent();
|
||||
while (true) {
|
||||
try {
|
||||
InputDevice di;
|
||||
|
||||
// block, doesn't release the monitor
|
||||
@@ -465,49 +470,81 @@ public abstract class KeyInputQueue {
|
||||
? KeyEvent.FLAG_WOKE_HERE : 0));
|
||||
} else if (ev.type == RawInputEvent.EV_KEY) {
|
||||
if (ev.scancode == RawInputEvent.BTN_TOUCH &&
|
||||
(classes&RawInputEvent.CLASS_TOUCHSCREEN) != 0) {
|
||||
(classes&(RawInputEvent.CLASS_TOUCHSCREEN
|
||||
|RawInputEvent.CLASS_TOUCHSCREEN_MT))
|
||||
== RawInputEvent.CLASS_TOUCHSCREEN) {
|
||||
di.mAbs.changed = true;
|
||||
di.mAbs.mDown[0] = ev.value != 0;
|
||||
} else if (ev.scancode == RawInputEvent.BTN_2 &&
|
||||
(classes&RawInputEvent.CLASS_TOUCHSCREEN) != 0) {
|
||||
(classes&(RawInputEvent.CLASS_TOUCHSCREEN
|
||||
|RawInputEvent.CLASS_TOUCHSCREEN_MT))
|
||||
== RawInputEvent.CLASS_TOUCHSCREEN) {
|
||||
di.mAbs.changed = true;
|
||||
di.mAbs.mDown[1] = ev.value != 0;
|
||||
} else if (ev.scancode == RawInputEvent.BTN_MOUSE &&
|
||||
(classes&RawInputEvent.CLASS_TRACKBALL) != 0) {
|
||||
di.mRel.changed = true;
|
||||
di.mRel.mDown[0] = ev.value != 0;
|
||||
di.mRel.mNextNumPointers = ev.value != 0 ? 1 : 0;
|
||||
send = true;
|
||||
}
|
||||
|
||||
} else if (ev.type == RawInputEvent.EV_ABS &&
|
||||
(classes&RawInputEvent.CLASS_TOUCHSCREEN_MT) != 0) {
|
||||
if (ev.scancode == RawInputEvent.ABS_MT_TOUCH_MAJOR) {
|
||||
di.mAbs.changed = true;
|
||||
di.mAbs.mNextData[di.mAbs.mAddingPointerOffset
|
||||
+ MotionEvent.SAMPLE_PRESSURE] = ev.value;
|
||||
} else if (ev.scancode == RawInputEvent.ABS_MT_POSITION_X) {
|
||||
di.mAbs.changed = true;
|
||||
di.mAbs.mNextData[di.mAbs.mAddingPointerOffset
|
||||
+ MotionEvent.SAMPLE_X] = ev.value;
|
||||
if (DEBUG_POINTERS) Log.v(TAG, "MT @"
|
||||
+ di.mAbs.mAddingPointerOffset
|
||||
+ " X:" + ev.value);
|
||||
} else if (ev.scancode == RawInputEvent.ABS_MT_POSITION_Y) {
|
||||
di.mAbs.changed = true;
|
||||
di.mAbs.mNextData[di.mAbs.mAddingPointerOffset
|
||||
+ MotionEvent.SAMPLE_Y] = ev.value;
|
||||
if (DEBUG_POINTERS) Log.v(TAG, "MT @"
|
||||
+ di.mAbs.mAddingPointerOffset
|
||||
+ " Y:" + ev.value);
|
||||
} else if (ev.scancode == RawInputEvent.ABS_MT_WIDTH_MAJOR) {
|
||||
di.mAbs.changed = true;
|
||||
di.mAbs.mNextData[di.mAbs.mAddingPointerOffset
|
||||
+ MotionEvent.SAMPLE_SIZE] = ev.value;
|
||||
}
|
||||
|
||||
} else if (ev.type == RawInputEvent.EV_ABS &&
|
||||
(classes&RawInputEvent.CLASS_TOUCHSCREEN) != 0) {
|
||||
// Finger 1
|
||||
if (ev.scancode == RawInputEvent.ABS_X) {
|
||||
di.mAbs.changed = true;
|
||||
di.mAbs.mCurData[MotionEvent.SAMPLE_X] = ev.value;
|
||||
di.mAbs.mNextData[MotionEvent.SAMPLE_X] = ev.value;
|
||||
} else if (ev.scancode == RawInputEvent.ABS_Y) {
|
||||
di.mAbs.changed = true;
|
||||
di.mAbs.mCurData[MotionEvent.SAMPLE_Y] = ev.value;
|
||||
di.mAbs.mNextData[MotionEvent.SAMPLE_Y] = ev.value;
|
||||
} else if (ev.scancode == RawInputEvent.ABS_PRESSURE) {
|
||||
di.mAbs.changed = true;
|
||||
di.mAbs.mCurData[MotionEvent.SAMPLE_PRESSURE] = ev.value;
|
||||
di.mAbs.mCurData[MotionEvent.NUM_SAMPLE_DATA
|
||||
di.mAbs.mNextData[MotionEvent.SAMPLE_PRESSURE] = ev.value;
|
||||
di.mAbs.mNextData[MotionEvent.NUM_SAMPLE_DATA
|
||||
+ MotionEvent.SAMPLE_PRESSURE] = ev.value;
|
||||
} else if (ev.scancode == RawInputEvent.ABS_TOOL_WIDTH) {
|
||||
di.mAbs.changed = true;
|
||||
di.mAbs.mCurData[MotionEvent.SAMPLE_SIZE] = ev.value;
|
||||
di.mAbs.mCurData[MotionEvent.NUM_SAMPLE_DATA
|
||||
di.mAbs.mNextData[MotionEvent.SAMPLE_SIZE] = ev.value;
|
||||
di.mAbs.mNextData[MotionEvent.NUM_SAMPLE_DATA
|
||||
+ MotionEvent.SAMPLE_SIZE] = ev.value;
|
||||
|
||||
// Finger 2
|
||||
} else if (ev.scancode == RawInputEvent.ABS_HAT0X) {
|
||||
di.mAbs.changed = true;
|
||||
di.mAbs.mCurData[MotionEvent.NUM_SAMPLE_DATA
|
||||
+ MotionEvent.SAMPLE_X] = ev.value;
|
||||
di.mAbs.mNextData[(di.mAbs.mDown[0] ?
|
||||
MotionEvent.NUM_SAMPLE_DATA : 0)
|
||||
+ MotionEvent.SAMPLE_X] = ev.value;
|
||||
} else if (ev.scancode == RawInputEvent.ABS_HAT0Y) {
|
||||
di.mAbs.changed = true;
|
||||
di.mAbs.mCurData[MotionEvent.NUM_SAMPLE_DATA
|
||||
+ MotionEvent.SAMPLE_Y] = ev.value;
|
||||
di.mAbs.mNextData[(di.mAbs.mDown[0] ?
|
||||
MotionEvent.NUM_SAMPLE_DATA : 0)
|
||||
+ MotionEvent.SAMPLE_Y] = ev.value;
|
||||
}
|
||||
|
||||
} else if (ev.type == RawInputEvent.EV_REL &&
|
||||
@@ -515,14 +552,40 @@ public abstract class KeyInputQueue {
|
||||
// Add this relative movement into our totals.
|
||||
if (ev.scancode == RawInputEvent.REL_X) {
|
||||
di.mRel.changed = true;
|
||||
di.mRel.mCurData[MotionEvent.SAMPLE_X] += ev.value;
|
||||
di.mRel.mNextData[MotionEvent.SAMPLE_X] += ev.value;
|
||||
} else if (ev.scancode == RawInputEvent.REL_Y) {
|
||||
di.mRel.changed = true;
|
||||
di.mRel.mCurData[MotionEvent.SAMPLE_Y] += ev.value;
|
||||
di.mRel.mNextData[MotionEvent.SAMPLE_Y] += ev.value;
|
||||
}
|
||||
}
|
||||
|
||||
if (send || ev.type == RawInputEvent.EV_SYN) {
|
||||
if (ev.type == RawInputEvent.EV_SYN
|
||||
&& ev.scancode == RawInputEvent.SYN_MT_REPORT
|
||||
&& di.mAbs != null) {
|
||||
di.mAbs.changed = true;
|
||||
if (di.mAbs.mNextData[MotionEvent.SAMPLE_PRESSURE] > 0) {
|
||||
// If the value is <= 0, the pointer is not
|
||||
// down, so keep it in the count.
|
||||
|
||||
if (di.mAbs.mNextData[di.mAbs.mAddingPointerOffset
|
||||
+ MotionEvent.SAMPLE_PRESSURE] != 0) {
|
||||
final int num = di.mAbs.mNextNumPointers+1;
|
||||
di.mAbs.mNextNumPointers = num;
|
||||
if (DEBUG_POINTERS) Log.v(TAG,
|
||||
"MT_REPORT: now have " + num + " pointers");
|
||||
final int newOffset = (num <= InputDevice.MAX_POINTERS)
|
||||
? (num * MotionEvent.NUM_SAMPLE_DATA)
|
||||
: (InputDevice.MAX_POINTERS *
|
||||
MotionEvent.NUM_SAMPLE_DATA);
|
||||
di.mAbs.mAddingPointerOffset = newOffset;
|
||||
di.mAbs.mNextData[newOffset
|
||||
+ MotionEvent.SAMPLE_PRESSURE] = 0;
|
||||
} else {
|
||||
if (DEBUG_POINTERS) Log.v(TAG, "MT_REPORT: no pointer");
|
||||
}
|
||||
}
|
||||
} else if (send || (ev.type == RawInputEvent.EV_SYN
|
||||
&& ev.scancode == RawInputEvent.SYN_REPORT)) {
|
||||
if (mDisplay != null) {
|
||||
if (!mHaveGlobalMetaState) {
|
||||
computeGlobalMetaStateLocked();
|
||||
@@ -534,72 +597,21 @@ public abstract class KeyInputQueue {
|
||||
if (ms.changed) {
|
||||
ms.changed = false;
|
||||
|
||||
boolean doMotion = true;
|
||||
|
||||
// Look for virtual buttons.
|
||||
VirtualKey vk = mPressedVirtualKey;
|
||||
if (vk != null) {
|
||||
doMotion = false;
|
||||
if (!ms.mDown[0]) {
|
||||
mPressedVirtualKey = null;
|
||||
ms.mLastDown[0] = ms.mDown[0];
|
||||
if (DEBUG_VIRTUAL_KEYS) Log.v(TAG,
|
||||
"Generate key up for: " + vk.scancode);
|
||||
KeyEvent event = newKeyEvent(di,
|
||||
di.mKeyDownTime, curTime, false,
|
||||
vk.lastKeycode,
|
||||
0, vk.scancode,
|
||||
KeyEvent.FLAG_VIRTUAL_HARD_KEY);
|
||||
mHapticFeedbackCallback.virtualKeyFeedback(event);
|
||||
addLocked(di, curTimeNano, ev.flags,
|
||||
RawInputEvent.CLASS_KEYBOARD,
|
||||
event);
|
||||
} else if (isInsideDisplay(di)) {
|
||||
// Whoops the pointer has moved into
|
||||
// the display area! Cancel the
|
||||
// virtual key and start a pointer
|
||||
// motion.
|
||||
mPressedVirtualKey = null;
|
||||
if (DEBUG_VIRTUAL_KEYS) Log.v(TAG,
|
||||
"Cancel key up for: " + vk.scancode);
|
||||
KeyEvent event = newKeyEvent(di,
|
||||
di.mKeyDownTime, curTime, false,
|
||||
vk.lastKeycode,
|
||||
0, vk.scancode,
|
||||
KeyEvent.FLAG_CANCELED |
|
||||
KeyEvent.FLAG_VIRTUAL_HARD_KEY);
|
||||
mHapticFeedbackCallback.virtualKeyFeedback(event);
|
||||
addLocked(di, curTimeNano, ev.flags,
|
||||
RawInputEvent.CLASS_KEYBOARD,
|
||||
event);
|
||||
doMotion = true;
|
||||
for (int i=InputDevice.MAX_POINTERS-1; i>=0; i--) {
|
||||
ms.mLastDown[i] = false;
|
||||
}
|
||||
}
|
||||
if ((classes&(RawInputEvent.CLASS_TOUCHSCREEN
|
||||
|RawInputEvent.CLASS_TOUCHSCREEN_MT))
|
||||
== RawInputEvent.CLASS_TOUCHSCREEN) {
|
||||
ms.mNextNumPointers = 0;
|
||||
if (ms.mDown[0]) ms.mNextNumPointers++;
|
||||
if (ms.mDown[1]) ms.mNextNumPointers++;
|
||||
}
|
||||
if (doMotion && ms.mDown[0] && !ms.mLastDown[0]) {
|
||||
vk = findSoftButton(di);
|
||||
if (vk != null) {
|
||||
doMotion = false;
|
||||
mPressedVirtualKey = vk;
|
||||
vk.lastKeycode = scancodeToKeycode(
|
||||
di.id, vk.scancode);
|
||||
ms.mLastDown[0] = ms.mDown[0];
|
||||
di.mKeyDownTime = curTime;
|
||||
if (DEBUG_VIRTUAL_KEYS) Log.v(TAG,
|
||||
"Generate key down for: " + vk.scancode
|
||||
+ " (keycode=" + vk.lastKeycode + ")");
|
||||
KeyEvent event = newKeyEvent(di,
|
||||
di.mKeyDownTime, curTime, true,
|
||||
vk.lastKeycode, 0,
|
||||
vk.scancode,
|
||||
KeyEvent.FLAG_VIRTUAL_HARD_KEY);
|
||||
mHapticFeedbackCallback.virtualKeyFeedback(event);
|
||||
addLocked(di, curTimeNano, ev.flags,
|
||||
RawInputEvent.CLASS_KEYBOARD,
|
||||
event);
|
||||
}
|
||||
|
||||
boolean doMotion = !monitorVirtualKey(di,
|
||||
ev, curTime, curTimeNano);
|
||||
|
||||
if (doMotion && ms.mNextNumPointers > 0
|
||||
&& ms.mLastNumPointers == 0) {
|
||||
doMotion = !generateVirtualKeyDown(di,
|
||||
ev, curTime, curTimeNano);
|
||||
}
|
||||
|
||||
if (doMotion) {
|
||||
@@ -607,22 +619,26 @@ public abstract class KeyInputQueue {
|
||||
// multiple events here, for example
|
||||
// if two fingers change up/down state
|
||||
// at the same time.
|
||||
me = ms.generateAbsMotion(di, curTime,
|
||||
curTimeNano, mDisplay,
|
||||
mOrientation, mGlobalMetaState);
|
||||
if (false) Log.v(TAG, "Absolute: x="
|
||||
+ di.mAbs.mCurData[MotionEvent.SAMPLE_X]
|
||||
+ " y="
|
||||
+ di.mAbs.mCurData[MotionEvent.SAMPLE_Y]
|
||||
+ " ev=" + me);
|
||||
if (me != null) {
|
||||
if (WindowManagerPolicy.WATCH_POINTER) {
|
||||
Log.i(TAG, "Enqueueing: " + me);
|
||||
do {
|
||||
me = ms.generateAbsMotion(di, curTime,
|
||||
curTimeNano, mDisplay,
|
||||
mOrientation, mGlobalMetaState);
|
||||
if (false) Log.v(TAG, "Absolute: x="
|
||||
+ di.mAbs.mNextData[MotionEvent.SAMPLE_X]
|
||||
+ " y="
|
||||
+ di.mAbs.mNextData[MotionEvent.SAMPLE_Y]
|
||||
+ " ev=" + me);
|
||||
if (me != null) {
|
||||
if (WindowManagerPolicy.WATCH_POINTER) {
|
||||
Log.i(TAG, "Enqueueing: " + me);
|
||||
}
|
||||
addLocked(di, curTimeNano, ev.flags,
|
||||
RawInputEvent.CLASS_TOUCHSCREEN, me);
|
||||
}
|
||||
addLocked(di, curTimeNano, ev.flags,
|
||||
RawInputEvent.CLASS_TOUCHSCREEN, me);
|
||||
}
|
||||
} while (ms.hasMore());
|
||||
}
|
||||
|
||||
ms.finish();
|
||||
}
|
||||
|
||||
ms = di.mRel;
|
||||
@@ -633,22 +649,24 @@ public abstract class KeyInputQueue {
|
||||
curTimeNano,
|
||||
mOrientation, mGlobalMetaState);
|
||||
if (false) Log.v(TAG, "Relative: x="
|
||||
+ di.mRel.mCurData[MotionEvent.SAMPLE_X]
|
||||
+ di.mRel.mNextData[MotionEvent.SAMPLE_X]
|
||||
+ " y="
|
||||
+ di.mRel.mCurData[MotionEvent.SAMPLE_Y]
|
||||
+ di.mRel.mNextData[MotionEvent.SAMPLE_Y]
|
||||
+ " ev=" + me);
|
||||
if (me != null) {
|
||||
addLocked(di, curTimeNano, ev.flags,
|
||||
RawInputEvent.CLASS_TRACKBALL, me);
|
||||
}
|
||||
|
||||
ms.finish();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} catch (RuntimeException exc) {
|
||||
Log.e(TAG, "InputReaderThread uncaught exception", exc);
|
||||
} catch (RuntimeException exc) {
|
||||
Log.e(TAG, "InputReaderThread uncaught exception", exc);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -661,13 +679,13 @@ public abstract class KeyInputQueue {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (absm.mCurData[MotionEvent.SAMPLE_X] >= absx.minValue
|
||||
&& absm.mCurData[MotionEvent.SAMPLE_X] <= absx.maxValue
|
||||
&& absm.mCurData[MotionEvent.SAMPLE_Y] >= absy.minValue
|
||||
&& absm.mCurData[MotionEvent.SAMPLE_Y] <= absy.maxValue) {
|
||||
if (absm.mNextData[MotionEvent.SAMPLE_X] >= absx.minValue
|
||||
&& absm.mNextData[MotionEvent.SAMPLE_X] <= absx.maxValue
|
||||
&& absm.mNextData[MotionEvent.SAMPLE_Y] >= absy.minValue
|
||||
&& absm.mNextData[MotionEvent.SAMPLE_Y] <= absy.maxValue) {
|
||||
if (DEBUG_VIRTUAL_KEYS) Log.v(TAG, "Input ("
|
||||
+ absm.mCurData[MotionEvent.SAMPLE_X]
|
||||
+ "," + absm.mCurData[MotionEvent.SAMPLE_Y]
|
||||
+ absm.mNextData[MotionEvent.SAMPLE_X]
|
||||
+ "," + absm.mNextData[MotionEvent.SAMPLE_Y]
|
||||
+ ") inside of display");
|
||||
return true;
|
||||
}
|
||||
@@ -675,28 +693,24 @@ public abstract class KeyInputQueue {
|
||||
return false;
|
||||
}
|
||||
|
||||
private VirtualKey findSoftButton(InputDevice dev) {
|
||||
private VirtualKey findVirtualKey(InputDevice dev) {
|
||||
final int N = mVirtualKeys.size();
|
||||
if (N <= 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (isInsideDisplay(dev)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final InputDevice.MotionState absm = dev.mAbs;
|
||||
for (int i=0; i<N; i++) {
|
||||
VirtualKey sb = mVirtualKeys.get(i);
|
||||
sb.computeHitRect(dev, mDisplayWidth, mDisplayHeight);
|
||||
if (DEBUG_VIRTUAL_KEYS) Log.v(TAG, "Hit test ("
|
||||
+ absm.mCurData[MotionEvent.SAMPLE_X] + ","
|
||||
+ absm.mCurData[MotionEvent.SAMPLE_Y] + ") in code "
|
||||
+ absm.mNextData[MotionEvent.SAMPLE_X] + ","
|
||||
+ absm.mNextData[MotionEvent.SAMPLE_Y] + ") in code "
|
||||
+ sb.scancode + " - (" + sb.hitLeft
|
||||
+ "," + sb.hitTop + ")-(" + sb.hitRight + ","
|
||||
+ sb.hitBottom + ")");
|
||||
if (sb.checkHit(absm.mCurData[MotionEvent.SAMPLE_X],
|
||||
absm.mCurData[MotionEvent.SAMPLE_Y])) {
|
||||
if (sb.checkHit(absm.mNextData[MotionEvent.SAMPLE_X],
|
||||
absm.mNextData[MotionEvent.SAMPLE_Y])) {
|
||||
if (DEBUG_VIRTUAL_KEYS) Log.v(TAG, "Hit!");
|
||||
return sb;
|
||||
}
|
||||
@@ -705,6 +719,97 @@ public abstract class KeyInputQueue {
|
||||
return null;
|
||||
}
|
||||
|
||||
private boolean generateVirtualKeyDown(InputDevice di, RawInputEvent ev,
|
||||
long curTime, long curTimeNano) {
|
||||
if (isInsideDisplay(di)) {
|
||||
// Didn't consume event.
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
VirtualKey vk = findVirtualKey(di);
|
||||
if (vk != null) {
|
||||
final InputDevice.MotionState ms = di.mAbs;
|
||||
mPressedVirtualKey = vk;
|
||||
vk.lastKeycode = scancodeToKeycode(di.id, vk.scancode);
|
||||
ms.mLastNumPointers = ms.mNextNumPointers;
|
||||
di.mKeyDownTime = curTime;
|
||||
if (DEBUG_VIRTUAL_KEYS) Log.v(TAG,
|
||||
"Generate key down for: " + vk.scancode
|
||||
+ " (keycode=" + vk.lastKeycode + ")");
|
||||
KeyEvent event = newKeyEvent(di, di.mKeyDownTime, curTime, true,
|
||||
vk.lastKeycode, 0, vk.scancode,
|
||||
KeyEvent.FLAG_VIRTUAL_HARD_KEY);
|
||||
mHapticFeedbackCallback.virtualKeyFeedback(event);
|
||||
addLocked(di, curTimeNano, ev.flags, RawInputEvent.CLASS_KEYBOARD,
|
||||
event);
|
||||
}
|
||||
|
||||
// We always consume the event, even if we didn't
|
||||
// generate a key event. There are two reasons for
|
||||
// this: to avoid spurious touches when holding
|
||||
// the edges of the device near the touchscreen,
|
||||
// and to avoid reporting events if there are virtual
|
||||
// keys on the touchscreen outside of the display
|
||||
// area.
|
||||
// Note that for all of this we are only looking at the
|
||||
// first pointer, since what we are handling here is the
|
||||
// first pointer going down, and this is the coordinate
|
||||
// that will be used to dispatch the event.
|
||||
if (false) {
|
||||
final InputDevice.AbsoluteInfo absx = di.absX;
|
||||
final InputDevice.AbsoluteInfo absy = di.absY;
|
||||
final InputDevice.MotionState absm = di.mAbs;
|
||||
Log.v(TAG, "Rejecting ("
|
||||
+ absm.mNextData[MotionEvent.SAMPLE_X] + ","
|
||||
+ absm.mNextData[MotionEvent.SAMPLE_Y] + "): outside of ("
|
||||
+ absx.minValue + "," + absy.minValue
|
||||
+ ")-(" + absx.maxValue + ","
|
||||
+ absx.maxValue + ")");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean monitorVirtualKey(InputDevice di, RawInputEvent ev,
|
||||
long curTime, long curTimeNano) {
|
||||
VirtualKey vk = mPressedVirtualKey;
|
||||
if (vk == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final InputDevice.MotionState ms = di.mAbs;
|
||||
if (ms.mNextNumPointers <= 0) {
|
||||
mPressedVirtualKey = null;
|
||||
ms.mLastNumPointers = 0;
|
||||
if (DEBUG_VIRTUAL_KEYS) Log.v(TAG, "Generate key up for: " + vk.scancode);
|
||||
KeyEvent event = newKeyEvent(di, di.mKeyDownTime, curTime, false,
|
||||
vk.lastKeycode, 0, vk.scancode,
|
||||
KeyEvent.FLAG_VIRTUAL_HARD_KEY);
|
||||
mHapticFeedbackCallback.virtualKeyFeedback(event);
|
||||
addLocked(di, curTimeNano, ev.flags, RawInputEvent.CLASS_KEYBOARD,
|
||||
event);
|
||||
return true;
|
||||
|
||||
} else if (isInsideDisplay(di)) {
|
||||
// Whoops the pointer has moved into
|
||||
// the display area! Cancel the
|
||||
// virtual key and start a pointer
|
||||
// motion.
|
||||
mPressedVirtualKey = null;
|
||||
if (DEBUG_VIRTUAL_KEYS) Log.v(TAG, "Cancel key up for: " + vk.scancode);
|
||||
KeyEvent event = newKeyEvent(di, di.mKeyDownTime, curTime, false,
|
||||
vk.lastKeycode, 0, vk.scancode,
|
||||
KeyEvent.FLAG_CANCELED | KeyEvent.FLAG_VIRTUAL_HARD_KEY);
|
||||
mHapticFeedbackCallback.virtualKeyFeedback(event);
|
||||
addLocked(di, curTimeNano, ev.flags, RawInputEvent.CLASS_KEYBOARD,
|
||||
event);
|
||||
ms.mLastNumPointers = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new meta state for the given keys and old state.
|
||||
*/
|
||||
@@ -851,8 +956,8 @@ public abstract class KeyInputQueue {
|
||||
if (ev.event == ev.inputDevice.mRel.currentMove) {
|
||||
if (false) Log.i(TAG, "Detach rel " + ev.event);
|
||||
ev.inputDevice.mRel.currentMove = null;
|
||||
ev.inputDevice.mRel.mCurData[MotionEvent.SAMPLE_X] = 0;
|
||||
ev.inputDevice.mRel.mCurData[MotionEvent.SAMPLE_Y] = 0;
|
||||
ev.inputDevice.mRel.mNextData[MotionEvent.SAMPLE_X] = 0;
|
||||
ev.inputDevice.mRel.mNextData[MotionEvent.SAMPLE_Y] = 0;
|
||||
}
|
||||
recycleLocked(ev);
|
||||
}
|
||||
@@ -945,7 +1050,12 @@ public abstract class KeyInputQueue {
|
||||
InputDevice.AbsoluteInfo absY;
|
||||
InputDevice.AbsoluteInfo absPressure;
|
||||
InputDevice.AbsoluteInfo absSize;
|
||||
if ((classes&RawInputEvent.CLASS_TOUCHSCREEN) != 0) {
|
||||
if ((classes&RawInputEvent.CLASS_TOUCHSCREEN_MT) != 0) {
|
||||
absX = loadAbsoluteInfo(deviceId, RawInputEvent.ABS_MT_POSITION_X, "X");
|
||||
absY = loadAbsoluteInfo(deviceId, RawInputEvent.ABS_MT_POSITION_Y, "Y");
|
||||
absPressure = loadAbsoluteInfo(deviceId, RawInputEvent.ABS_MT_TOUCH_MAJOR, "Pressure");
|
||||
absSize = loadAbsoluteInfo(deviceId, RawInputEvent.ABS_MT_WIDTH_MAJOR, "Size");
|
||||
} else if ((classes&RawInputEvent.CLASS_TOUCHSCREEN) != 0) {
|
||||
absX = loadAbsoluteInfo(deviceId, RawInputEvent.ABS_X, "X");
|
||||
absY = loadAbsoluteInfo(deviceId, RawInputEvent.ABS_Y, "Y");
|
||||
absPressure = loadAbsoluteInfo(deviceId, RawInputEvent.ABS_PRESSURE, "Pressure");
|
||||
|
||||
Reference in New Issue
Block a user