summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--api/current.txt30
-rw-r--r--core/java/android/inputmethodservice/SoftInputWindow.java57
-rwxr-xr-xcore/java/android/view/InputDevice.java10
-rwxr-xr-xcore/java/android/view/KeyEvent.java25
-rw-r--r--core/java/android/view/MotionEvent.java1020
-rw-r--r--core/java/android/view/View.java35
-rw-r--r--core/java/android/view/ViewGroup.java174
-rw-r--r--core/java/android/widget/AbsListView.java21
-rw-r--r--core/java/com/android/internal/widget/PointerLocationView.java34
-rw-r--r--core/jni/android_view_MotionEvent.cpp150
-rw-r--r--include/ui/Input.h59
-rw-r--r--include/ui/InputTransport.h6
-rw-r--r--libs/ui/Input.cpp45
-rw-r--r--libs/ui/InputTransport.cpp16
-rw-r--r--libs/ui/tests/InputEvent_test.cpp25
-rw-r--r--libs/ui/tests/InputPublisherAndConsumer_test.cpp72
-rw-r--r--native/android/input.cpp8
-rw-r--r--native/include/android/input.h38
-rw-r--r--services/input/InputDispatcher.cpp385
-rw-r--r--services/input/InputDispatcher.h25
-rw-r--r--services/input/InputReader.cpp275
-rw-r--r--services/input/InputReader.h28
-rw-r--r--services/input/PointerController.cpp4
-rw-r--r--services/input/PointerController.h10
-rw-r--r--services/input/tests/InputDispatcher_test.cpp54
-rw-r--r--services/input/tests/InputReader_test.cpp159
-rw-r--r--services/java/com/android/server/accessibility/TouchExplorer.java97
27 files changed, 1989 insertions, 873 deletions
diff --git a/api/current.txt b/api/current.txt
index 12fa844..86703ba 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -20158,6 +20158,7 @@ package android.view {
field public static final int SOURCE_JOYSTICK = 16777232; // 0x1000010
field public static final int SOURCE_KEYBOARD = 257; // 0x101
field public static final int SOURCE_MOUSE = 8194; // 0x2002
+ field public static final int SOURCE_STYLUS = 16386; // 0x4002
field public static final int SOURCE_TOUCHPAD = 1048584; // 0x100008
field public static final int SOURCE_TOUCHSCREEN = 4098; // 0x1002
field public static final int SOURCE_TRACKBALL = 65540; // 0x10004
@@ -20690,6 +20691,7 @@ package android.view {
method public final int getActionMasked();
method public final float getAxisValue(int);
method public final float getAxisValue(int, int);
+ method public final int getButtonState();
method public final int getDeviceId();
method public final long getDownTime();
method public final int getEdgeFlags();
@@ -20724,6 +20726,7 @@ package android.view {
method public final void getPointerCoords(int, android.view.MotionEvent.PointerCoords);
method public final int getPointerCount();
method public final int getPointerId(int);
+ method public final void getPointerProperties(int, android.view.MotionEvent.PointerProperties);
method public final float getPressure();
method public final float getPressure(int);
method public final float getRawX();
@@ -20735,6 +20738,7 @@ package android.view {
method public final float getToolMajor(int);
method public final float getToolMinor();
method public final float getToolMinor(int);
+ method public final int getToolType(int);
method public final float getTouchMajor();
method public final float getTouchMajor(int);
method public final float getTouchMinor();
@@ -20745,7 +20749,8 @@ package android.view {
method public final float getY();
method public final float getY(int);
method public final float getYPrecision();
- method public static android.view.MotionEvent obtain(long, long, int, int, int[], android.view.MotionEvent.PointerCoords[], int, float, float, int, int, int, int);
+ method public static android.view.MotionEvent obtain(long, long, int, int, android.view.MotionEvent.PointerProperties[], android.view.MotionEvent.PointerCoords[], int, int, float, float, int, int, int, int);
+ method public static deprecated android.view.MotionEvent obtain(long, long, int, int, int[], android.view.MotionEvent.PointerCoords[], int, float, float, int, int, int, int);
method public static android.view.MotionEvent obtain(long, long, int, float, float, float, float, int, float, float, int, int);
method public static deprecated android.view.MotionEvent obtain(long, long, int, int, float, float, float, float, int, float, float, int, int);
method public static android.view.MotionEvent obtain(long, long, int, float, float, int);
@@ -20782,6 +20787,7 @@ package android.view {
field public static final int ACTION_SCROLL = 8; // 0x8
field public static final int ACTION_UP = 1; // 0x1
field public static final int AXIS_BRAKE = 23; // 0x17
+ field public static final int AXIS_DISTANCE = 24; // 0x18
field public static final int AXIS_GAS = 22; // 0x16
field public static final int AXIS_GENERIC_1 = 32; // 0x20
field public static final int AXIS_GENERIC_10 = 41; // 0x29
@@ -20821,12 +20827,25 @@ package android.view {
field public static final int AXIS_X = 0; // 0x0
field public static final int AXIS_Y = 1; // 0x1
field public static final int AXIS_Z = 11; // 0xb
+ field public static final int BUTTON_BACK = 8; // 0x8
+ field public static final int BUTTON_ERASER = 32; // 0x20
+ field public static final int BUTTON_FORWARD = 16; // 0x10
+ field public static final int BUTTON_PRIMARY = 1; // 0x1
+ field public static final int BUTTON_SECONDARY = 2; // 0x2
+ field public static final int BUTTON_TERTIARY = 4; // 0x4
field public static final android.os.Parcelable.Creator CREATOR;
field public static final int EDGE_BOTTOM = 2; // 0x2
field public static final int EDGE_LEFT = 4; // 0x4
field public static final int EDGE_RIGHT = 8; // 0x8
field public static final int EDGE_TOP = 1; // 0x1
field public static final int FLAG_WINDOW_IS_OBSCURED = 1; // 0x1
+ field public static final int INVALID_POINTER_ID = -1; // 0xffffffff
+ field public static final int TOOL_TYPE_FINGER = 1; // 0x1
+ field public static final int TOOL_TYPE_INDIRECT_FINGER = 4; // 0x4
+ field public static final int TOOL_TYPE_INDIRECT_STYLUS = 5; // 0x5
+ field public static final int TOOL_TYPE_MOUSE = 3; // 0x3
+ field public static final int TOOL_TYPE_STYLUS = 2; // 0x2
+ field public static final int TOOL_TYPE_UNKNOWN = 0; // 0x0
}
public static final class MotionEvent.PointerCoords {
@@ -20847,6 +20866,15 @@ package android.view {
field public float y;
}
+ public static final class MotionEvent.PointerProperties {
+ ctor public MotionEvent.PointerProperties();
+ ctor public MotionEvent.PointerProperties(android.view.MotionEvent.PointerProperties);
+ method public void clear();
+ method public void copyFrom(android.view.MotionEvent.PointerProperties);
+ field public int id;
+ field public int toolType;
+ }
+
public abstract class OrientationEventListener {
ctor public OrientationEventListener(android.content.Context);
ctor public OrientationEventListener(android.content.Context, int);
diff --git a/core/java/android/inputmethodservice/SoftInputWindow.java b/core/java/android/inputmethodservice/SoftInputWindow.java
index 343242e..7159260 100644
--- a/core/java/android/inputmethodservice/SoftInputWindow.java
+++ b/core/java/android/inputmethodservice/SoftInputWindow.java
@@ -73,8 +73,17 @@ class SoftInputWindow extends Dialog {
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
getWindow().getDecorView().getHitRect(mBounds);
- final MotionEvent event = clipMotionEvent(ev, mBounds);
- return super.dispatchTouchEvent(event);
+
+ if (ev.isWithinBoundsNoHistory(mBounds.left, mBounds.top,
+ mBounds.right - 1, mBounds.bottom - 1)) {
+ return super.dispatchTouchEvent(ev);
+ } else {
+ MotionEvent temp = ev.clampNoHistory(mBounds.left, mBounds.top,
+ mBounds.right - 1, mBounds.bottom - 1);
+ boolean handled = super.dispatchTouchEvent(temp);
+ temp.recycle();
+ return handled;
+ }
}
/**
@@ -163,48 +172,4 @@ class SoftInputWindow extends Dialog {
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
WindowManager.LayoutParams.FLAG_DIM_BEHIND);
}
-
- private static MotionEvent clipMotionEvent(MotionEvent me, Rect bounds) {
- final int pointerCount = me.getPointerCount();
- boolean shouldClip = false;
- for (int pointerIndex = 0; pointerIndex < pointerCount; pointerIndex++) {
- final int x = (int)me.getX(pointerIndex);
- final int y = (int)me.getY(pointerIndex);
- if (!bounds.contains(x, y)) {
- shouldClip = true;
- break;
- }
- }
- if (!shouldClip)
- return me;
-
- if (pointerCount == 1) {
- final int x = (int)me.getX();
- final int y = (int)me.getY();
- me.setLocation(
- Math.max(bounds.left, Math.min(x, bounds.right - 1)),
- Math.max(bounds.top, Math.min(y, bounds.bottom - 1)));
- return me;
- }
-
- final int[] pointerIds = new int[pointerCount];
- final MotionEvent.PointerCoords[] pointerCoords =
- new MotionEvent.PointerCoords[pointerCount];
- for (int pointerIndex = 0; pointerIndex < pointerCount; pointerIndex++) {
- pointerIds[pointerIndex] = me.getPointerId(pointerIndex);
- final MotionEvent.PointerCoords coords = new MotionEvent.PointerCoords();
- me.getPointerCoords(pointerIndex, coords);
- pointerCoords[pointerIndex] = coords;
- final int x = (int)coords.x;
- final int y = (int)coords.y;
- if (!bounds.contains(x, y)) {
- coords.x = Math.max(bounds.left, Math.min(x, bounds.right - 1));
- coords.y = Math.max(bounds.top, Math.min(y, bounds.bottom - 1));
- }
- }
- return MotionEvent.obtain(
- me.getDownTime(), me.getEventTime(), me.getAction(), pointerCount, pointerIds,
- pointerCoords, me.getMetaState(), me.getXPrecision(), me.getYPrecision(),
- me.getDeviceId(), me.getEdgeFlags(), me.getSource(), me.getFlags());
- }
}
diff --git a/core/java/android/view/InputDevice.java b/core/java/android/view/InputDevice.java
index 8cb68f9..bfc7c31 100755
--- a/core/java/android/view/InputDevice.java
+++ b/core/java/android/view/InputDevice.java
@@ -153,7 +153,14 @@ public final class InputDevice implements Parcelable {
* @see #SOURCE_CLASS_POINTER
*/
public static final int SOURCE_MOUSE = 0x00002000 | SOURCE_CLASS_POINTER;
-
+
+ /**
+ * The input source is a stylus pointing device.
+ *
+ * @see #SOURCE_CLASS_POINTER
+ */
+ public static final int SOURCE_STYLUS = 0x00004000 | SOURCE_CLASS_POINTER;
+
/**
* The input source is a trackball.
*
@@ -585,6 +592,7 @@ public final class InputDevice implements Parcelable {
appendSourceDescriptionIfApplicable(description, SOURCE_DPAD, "dpad");
appendSourceDescriptionIfApplicable(description, SOURCE_TOUCHSCREEN, "touchscreen");
appendSourceDescriptionIfApplicable(description, SOURCE_MOUSE, "mouse");
+ appendSourceDescriptionIfApplicable(description, SOURCE_STYLUS, "stylus");
appendSourceDescriptionIfApplicable(description, SOURCE_TRACKBALL, "trackball");
appendSourceDescriptionIfApplicable(description, SOURCE_TOUCHPAD, "touchpad");
appendSourceDescriptionIfApplicable(description, SOURCE_JOYSTICK, "joystick");
diff --git a/core/java/android/view/KeyEvent.java b/core/java/android/view/KeyEvent.java
index 13d8809..5dbda90 100755
--- a/core/java/android/view/KeyEvent.java
+++ b/core/java/android/view/KeyEvent.java
@@ -2672,15 +2672,22 @@ public class KeyEvent extends InputEvent implements Parcelable {
@Override
public String toString() {
- return "KeyEvent{action=" + actionToString(mAction)
- + " keycode=" + keyCodeToString(mKeyCode)
- + " scancode=" + mScanCode
- + " metaState=" + metaStateToString(mMetaState)
- + " flags=0x" + Integer.toHexString(mFlags)
- + " repeat=" + mRepeatCount
- + " device=" + mDeviceId
- + " source=0x" + Integer.toHexString(mSource)
- + "}";
+ StringBuilder msg = new StringBuilder();
+ msg.append("KeyEvent { action=").append(actionToString(mAction));
+ msg.append(", keyCode=").append(keyCodeToString(mKeyCode));
+ msg.append(", scanCode=").append(mScanCode);
+ if (mCharacters != null) {
+ msg.append(", characters=\"").append(mCharacters).append("\"");
+ }
+ msg.append(", metaState=").append(metaStateToString(mMetaState));
+ msg.append(", flags=0x").append(Integer.toHexString(mFlags));
+ msg.append(", repeatCount=").append(mRepeatCount);
+ msg.append(", eventTime=").append(mEventTime);
+ msg.append(", downTime=").append(mDownTime);
+ msg.append(", deviceId=").append(mDeviceId);
+ msg.append(", source=0x").append(Integer.toHexString(mSource));
+ msg.append(" }");
+ return msg.toString();
}
/**
diff --git a/core/java/android/view/MotionEvent.java b/core/java/android/view/MotionEvent.java
index 7611b08..82fd581 100644
--- a/core/java/android/view/MotionEvent.java
+++ b/core/java/android/view/MotionEvent.java
@@ -23,53 +23,60 @@ import android.os.SystemClock;
import android.util.SparseArray;
/**
- * Object used to report movement (mouse, pen, finger, trackball) events. This
- * class may hold either absolute or relative movements, depending on what
- * it is being used for.
+ * Object used to report movement (mouse, pen, finger, trackball) events.
+ * Motion events may hold either absolute or relative movements and other data,
+ * depending on the type of device.
+ *
+ * <h3>Overview</h3>
* <p>
- * On pointing devices with source class {@link InputDevice#SOURCE_CLASS_POINTER}
- * such as touch screens, the pointer coordinates specify absolute
- * positions such as view X/Y coordinates. Each complete gesture is represented
- * by a sequence of motion events with actions that describe pointer state transitions
- * and movements. A gesture starts with a motion event with {@link #ACTION_DOWN}
- * that provides the location of the first pointer down. As each additional
- * pointer that goes down or up, the framework will generate a motion event with
- * {@link #ACTION_POINTER_DOWN} or {@link #ACTION_POINTER_UP} accordingly.
- * Pointer movements are described by motion events with {@link #ACTION_MOVE}.
- * Finally, a gesture end either when the final pointer goes up as represented
- * by a motion event with {@link #ACTION_UP} or when gesture is canceled
- * with {@link #ACTION_CANCEL}.
+ * Motion events describe movements in terms of an action code and a set of axis values.
+ * The action code specifies the state change that occurred such as a pointer going
+ * down or up. The axis values describe the position and other movement properties.
* </p><p>
- * Some pointing devices such as mice may support vertical and/or horizontal scrolling.
- * A scroll event is reported as a generic motion event with {@link #ACTION_SCROLL} that
- * includes the relative scroll offset in the {@link #AXIS_VSCROLL} and
- * {@link #AXIS_HSCROLL} axes. See {@link #getAxisValue(int)} for information
- * about retrieving these additional axes.
+ * For example, when the user first touches the screen, the system delivers a touch
+ * event to the appropriate {@link View} with the action code {@link #ACTION_DOWN}
+ * and a set of axis values that include the X and Y coordinates of the touch and
+ * information about the pressure, size and orientation of the contact area.
* </p><p>
- * On trackball devices with source class {@link InputDevice#SOURCE_CLASS_TRACKBALL},
- * the pointer coordinates specify relative movements as X/Y deltas.
- * A trackball gesture consists of a sequence of movements described by motion
- * events with {@link #ACTION_MOVE} interspersed with occasional {@link #ACTION_DOWN}
- * or {@link #ACTION_UP} motion events when the trackball button is pressed or released.
+ * Some devices can report multiple movement traces at the same time. Multi-touch
+ * screens emit one movement trace for each finger. The individual fingers or
+ * other objects that generate movement traces are referred to as <em>pointers</em>.
+ * Motion events contain information about all of the pointers that are currently active
+ * even if some of them have not moved since the last event was delivered.
* </p><p>
- * On joystick devices with source class {@link InputDevice#SOURCE_CLASS_JOYSTICK},
- * the pointer coordinates specify the absolute position of the joystick axes.
- * The joystick axis values are normalized to a range of -1.0 to 1.0 where 0.0 corresponds
- * to the center position. More information about the set of available axes and the
- * range of motion can be obtained using {@link InputDevice#getMotionRange}.
- * Some common joystick axes are {@link #AXIS_X}, {@link #AXIS_Y},
- * {@link #AXIS_HAT_X}, {@link #AXIS_HAT_Y}, {@link #AXIS_Z} and {@link #AXIS_RZ}.
- * </p><p>
- * Motion events always report movements for all pointers at once. The number
- * of pointers only ever changes by one as individual pointers go up and down,
+ * The number of pointers only ever changes by one as individual pointers go up and down,
* except when the gesture is canceled.
* </p><p>
- * The order in which individual pointers appear within a motion event can change
- * from one event to the next. Use the {@link #getPointerId(int)} method to obtain a
- * pointer id to track pointers across motion events in a gesture. Then for
- * successive motion events, use the {@link #findPointerIndex(int)} method to obtain
- * the pointer index for a given pointer id in that motion event.
+ * Each pointer has a unique id that is assigned when it first goes down
+ * (indicated by {@link #ACTION_DOWN} or {@link #ACTION_POINTER_DOWN}). A pointer id
+ * remains valid until the pointer eventually goes up (indicated by {@link #ACTION_UP}
+ * or {@link #ACTION_POINTER_UP}) or when the gesture is canceled (indicated by
+ * {@link #ACTION_CANCEL}).
+ * </p><p>
+ * The MotionEvent class provides many methods to query the position and other properties of
+ * pointers, such as {@link #getX(int)}, {@link #getY(int)}, {@link #getAxisValue},
+ * {@link #getPointerId(int)}, {@link #getToolType(int)}, and many others. Most of these
+ * methods accept the pointer index as a parameter rather than the pointer id.
+ * The pointer index of each pointer in the event ranges from 0 to one less than the value
+ * returned by {@link #getPointerCount()}.
* </p><p>
+ * The order in which individual pointers appear within a motion event is undefined.
+ * Thus the pointer index of a pointer can change from one event to the next but
+ * the pointer id of a pointer is guaranteed to remain constant as long as the pointer
+ * remains active. Use the {@link #getPointerId(int)} method to obtain the
+ * pointer id of a pointer to track it across all subsequent motion events in a gesture.
+ * Then for successive motion events, use the {@link #findPointerIndex(int)} method
+ * to obtain the pointer index for a given pointer id in that motion event.
+ * </p><p>
+ * Mouse and stylus buttons can be retrieved using {@link #getButtonState()}. It is a
+ * good idea to check the button state while handling {@link #ACTION_DOWN} as part
+ * of a touch event. The application may choose to perform some different action
+ * if the touch event starts due to a secondary button click, such as presenting a
+ * context menu.
+ * </p>
+ *
+ * <h3>Batching</h3>
+ * <p>
* For efficiency, motion events with {@link #ACTION_MOVE} may batch together
* multiple movement samples within a single object. The most current
* pointer coordinates are available using {@link #getX(int)} and {@link #getY(int)}.
@@ -98,42 +105,104 @@ import android.util.SparseArray;
* ev.getPointerId(p), ev.getX(p), ev.getY(p));
* }
* }
- * </code></pre></p><p>
- * In general, the framework cannot guarantee that the motion events it delivers
- * to a view always constitute a complete motion sequences since some events may be dropped
- * or modified by containing views before they are delivered. The view implementation
- * should be prepared to handle {@link #ACTION_CANCEL} and should tolerate anomalous
- * situations such as receiving a new {@link #ACTION_DOWN} without first having
- * received an {@link #ACTION_UP} for the prior gesture.
+ * </code></pre></p>
+ *
+ * <h3>Device Types</h3>
+ * <p>
+ * The interpretation of the contents of a MotionEvent varies significantly depending
+ * on the source class of the device.
+ * </p><p>
+ * On pointing devices with source class {@link InputDevice#SOURCE_CLASS_POINTER}
+ * such as touch screens, the pointer coordinates specify absolute
+ * positions such as view X/Y coordinates. Each complete gesture is represented
+ * by a sequence of motion events with actions that describe pointer state transitions
+ * and movements. A gesture starts with a motion event with {@link #ACTION_DOWN}
+ * that provides the location of the first pointer down. As each additional
+ * pointer that goes down or up, the framework will generate a motion event with
+ * {@link #ACTION_POINTER_DOWN} or {@link #ACTION_POINTER_UP} accordingly.
+ * Pointer movements are described by motion events with {@link #ACTION_MOVE}.
+ * Finally, a gesture end either when the final pointer goes up as represented
+ * by a motion event with {@link #ACTION_UP} or when gesture is canceled
+ * with {@link #ACTION_CANCEL}.
+ * </p><p>
+ * Some pointing devices such as mice may support vertical and/or horizontal scrolling.
+ * A scroll event is reported as a generic motion event with {@link #ACTION_SCROLL} that
+ * includes the relative scroll offset in the {@link #AXIS_VSCROLL} and
+ * {@link #AXIS_HSCROLL} axes. See {@link #getAxisValue(int)} for information
+ * about retrieving these additional axes.
+ * </p><p>
+ * On trackball devices with source class {@link InputDevice#SOURCE_CLASS_TRACKBALL},
+ * the pointer coordinates specify relative movements as X/Y deltas.
+ * A trackball gesture consists of a sequence of movements described by motion
+ * events with {@link #ACTION_MOVE} interspersed with occasional {@link #ACTION_DOWN}
+ * or {@link #ACTION_UP} motion events when the trackball button is pressed or released.
+ * </p><p>
+ * On joystick devices with source class {@link InputDevice#SOURCE_CLASS_JOYSTICK},
+ * the pointer coordinates specify the absolute position of the joystick axes.
+ * The joystick axis values are normalized to a range of -1.0 to 1.0 where 0.0 corresponds
+ * to the center position. More information about the set of available axes and the
+ * range of motion can be obtained using {@link InputDevice#getMotionRange}.
+ * Some common joystick axes are {@link #AXIS_X}, {@link #AXIS_Y},
+ * {@link #AXIS_HAT_X}, {@link #AXIS_HAT_Y}, {@link #AXIS_Z} and {@link #AXIS_RZ}.
* </p><p>
* Refer to {@link InputDevice} for more information about how different kinds of
* input devices and sources represent pointer coordinates.
* </p>
+ *
+ * <h3>Consistency Guarantees</h3>
+ * <p>
+ * Motion events are always delivered to views as a consistent stream of events.
+ * What constitutes a consistent stream varies depending on the type of device.
+ * For touch events, consistency implies that pointers go down one at a time,
+ * move around as a group and then go up one at a time or are canceled.
+ * </p><p>
+ * While the framework tries to deliver consistent streams of motion events to
+ * views, it cannot guarantee it. Some events may be dropped or modified by
+ * containing views in the application before they are delivered thereby making
+ * the stream of events inconsistent. Views should always be prepared to
+ * handle {@link #ACTION_CANCEL} and should tolerate anomalous
+ * situations such as receiving a new {@link #ACTION_DOWN} without first having
+ * received an {@link #ACTION_UP} for the prior gesture.
+ * </p>
*/
public final class MotionEvent extends InputEvent implements Parcelable {
private static final long NS_PER_MS = 1000000;
private static final boolean TRACK_RECYCLED_LOCATION = false;
-
+
+ /**
+ * An invalid pointer id.
+ *
+ * This value (-1) can be used as a placeholder to indicate that a pointer id
+ * has not been assigned or is not available. It cannot appear as
+ * a pointer id inside a {@link MotionEvent}.
+ */
+ public static final int INVALID_POINTER_ID = -1;
+
/**
* Bit mask of the parts of the action code that are the action itself.
*/
public static final int ACTION_MASK = 0xff;
/**
- * Constant for {@link #getAction}: A pressed gesture has started, the
+ * Constant for {@link #getActionMasked}: A pressed gesture has started, the
* motion contains the initial starting location.
+ * <p>
+ * This is also a good time to check the button state to distinguish
+ * secondary and tertiary button clicks and handle them appropriately.
+ * Use {@link #getButtonState} to retrieve the button state.
+ * </p>
*/
public static final int ACTION_DOWN = 0;
/**
- * Constant for {@link #getAction}: A pressed gesture has finished, the
+ * Constant for {@link #getActionMasked}: A pressed gesture has finished, the
* motion contains the final release location as well as any intermediate
* points since the last down or move event.
*/
public static final int ACTION_UP = 1;
/**
- * Constant for {@link #getAction}: A change has happened during a
+ * Constant for {@link #getActionMasked}: A change has happened during a
* press gesture (between {@link #ACTION_DOWN} and {@link #ACTION_UP}).
* The motion contains the most recent point, as well as any intermediate
* points since the last down or move event.
@@ -141,33 +210,43 @@ public final class MotionEvent extends InputEvent implements Parcelable {
public static final int ACTION_MOVE = 2;
/**
- * Constant for {@link #getAction}: The current gesture has been aborted.
+ * Constant for {@link #getActionMasked}: The current gesture has been aborted.
* You will not receive any more points in it. You should treat this as
* an up event, but not perform any action that you normally would.
*/
public static final int ACTION_CANCEL = 3;
/**
- * Constant for {@link #getAction}: A movement has happened outside of the
+ * Constant for {@link #getActionMasked}: A movement has happened outside of the
* normal bounds of the UI element. This does not provide a full gesture,
* but only the initial location of the movement/touch.
*/
public static final int ACTION_OUTSIDE = 4;
/**
- * A non-primary pointer has gone down. The bits in
- * {@link #ACTION_POINTER_ID_MASK} indicate which pointer changed.
+ * Constant for {@link #getActionMasked}: A non-primary pointer has gone down.
+ * <p>
+ * Use {@link #getActionIndex} to retrieve the index of the pointer that changed.
+ * </p><p>
+ * The index is encoded in the {@link #ACTION_POINTER_INDEX_MASK} bits of the
+ * unmasked action returned by {@link #getAction}.
+ * </p>
*/
public static final int ACTION_POINTER_DOWN = 5;
/**
- * A non-primary pointer has gone up. The bits in
- * {@link #ACTION_POINTER_ID_MASK} indicate which pointer changed.
+ * Constant for {@link #getActionMasked}: A non-primary pointer has gone up.
+ * <p>
+ * Use {@link #getActionIndex} to retrieve the index of the pointer that changed.
+ * </p><p>
+ * The index is encoded in the {@link #ACTION_POINTER_INDEX_MASK} bits of the
+ * unmasked action returned by {@link #getAction}.
+ * </p>
*/
public static final int ACTION_POINTER_UP = 6;
/**
- * Constant for {@link #getAction}: A change happened but the pointer
+ * Constant for {@link #getActionMasked}: A change happened but the pointer
* is not down (unlike {@link #ACTION_MOVE}). The motion contains the most
* recent point, as well as any intermediate points since the last
* hover move event.
@@ -182,14 +261,14 @@ public final class MotionEvent extends InputEvent implements Parcelable {
public static final int ACTION_HOVER_MOVE = 7;
/**
- * Constant for {@link #getAction}: The motion event contains relative
+ * Constant for {@link #getActionMasked}: The motion event contains relative
* vertical and/or horizontal scroll offsets. Use {@link #getAxisValue(int)}
* to retrieve the information from {@link #AXIS_VSCROLL} and {@link #AXIS_HSCROLL}.
* The pointer may or may not be down when this event is dispatched.
- * <p></p>
+ * <p>
* This action is always delivered to the window or view under the pointer, which
* may not be the window or view currently touched.
- * <p>
+ * </p><p>
* This action is not a touch event so it is delivered to
* {@link View#onGenericMotionEvent(MotionEvent)} rather than
* {@link View#onTouchEvent(MotionEvent)}.
@@ -198,7 +277,7 @@ public final class MotionEvent extends InputEvent implements Parcelable {
public static final int ACTION_SCROLL = 8;
/**
- * Constant for {@link #getAction}: The pointer is not down but has entered the
+ * Constant for {@link #getActionMasked}: The pointer is not down but has entered the
* boundaries of a window or view.
* <p>
* This action is always delivered to the window or view under the pointer.
@@ -211,7 +290,7 @@ public final class MotionEvent extends InputEvent implements Parcelable {
public static final int ACTION_HOVER_ENTER = 9;
/**
- * Constant for {@link #getAction}: The pointer is not down but has exited the
+ * Constant for {@link #getActionMasked}: The pointer is not down but has exited the
* boundaries of a window or view.
* <p>
* This action is always delivered to the window or view that was previously under the pointer.
@@ -230,15 +309,19 @@ public final class MotionEvent extends InputEvent implements Parcelable {
* index where the data for the pointer going up or down can be found; you can
* get its identifier with {@link #getPointerId(int)} and the actual
* data with {@link #getX(int)} etc.
+ *
+ * @see #getActionIndex
*/
public static final int ACTION_POINTER_INDEX_MASK = 0xff00;
/**
* Bit shift for the action bits holding the pointer index as
* defined by {@link #ACTION_POINTER_INDEX_MASK}.
+ *
+ * @see #getActionIndex
*/
public static final int ACTION_POINTER_INDEX_SHIFT = 8;
-
+
/**
* @deprecated Use {@link #ACTION_POINTER_INDEX_MASK} to retrieve the
* data index associated with {@link #ACTION_POINTER_DOWN}.
@@ -339,7 +422,7 @@ public final class MotionEvent extends InputEvent implements Parcelable {
public static final int EDGE_RIGHT = 0x00000008;
/**
- * Constant used to identify the X axis of a motion event.
+ * Axis constant: X axis of a motion event.
* <p>
* <ul>
* <li>For a touch screen, reports the absolute X screen position of the center of
@@ -364,7 +447,7 @@ public final class MotionEvent extends InputEvent implements Parcelable {
public static final int AXIS_X = 0;
/**
- * Constant used to identify the Y axis of a motion event.
+ * Axis constant: Y axis of a motion event.
* <p>
* <ul>
* <li>For a touch screen, reports the absolute Y screen position of the center of
@@ -389,7 +472,7 @@ public final class MotionEvent extends InputEvent implements Parcelable {
public static final int AXIS_Y = 1;
/**
- * Constant used to identify the Pressure axis of a motion event.
+ * Axis constant: Pressure axis of a motion event.
* <p>
* <ul>
* <li>For a touch screen or touch pad, reports the approximate pressure applied to the surface
@@ -411,7 +494,7 @@ public final class MotionEvent extends InputEvent implements Parcelable {
public static final int AXIS_PRESSURE = 2;
/**
- * Constant used to identify the Size axis of a motion event.
+ * Axis constant: Size axis of a motion event.
* <p>
* <ul>
* <li>For a touch screen or touch pad, reports the approximate size of the contact area in
@@ -431,7 +514,7 @@ public final class MotionEvent extends InputEvent implements Parcelable {
public static final int AXIS_SIZE = 3;
/**
- * Constant used to identify the TouchMajor axis of a motion event.
+ * Axis constant: TouchMajor axis of a motion event.
* <p>
* <ul>
* <li>For a touch screen, reports the length of the major axis of an ellipse that
@@ -452,7 +535,7 @@ public final class MotionEvent extends InputEvent implements Parcelable {
public static final int AXIS_TOUCH_MAJOR = 4;
/**
- * Constant used to identify the TouchMinor axis of a motion event.
+ * Axis constant: TouchMinor axis of a motion event.
* <p>
* <ul>
* <li>For a touch screen, reports the length of the minor axis of an ellipse that
@@ -475,7 +558,7 @@ public final class MotionEvent extends InputEvent implements Parcelable {
public static final int AXIS_TOUCH_MINOR = 5;
/**
- * Constant used to identify the ToolMajor axis of a motion event.
+ * Axis constant: ToolMajor axis of a motion event.
* <p>
* <ul>
* <li>For a touch screen, reports the length of the major axis of an ellipse that
@@ -500,7 +583,7 @@ public final class MotionEvent extends InputEvent implements Parcelable {
public static final int AXIS_TOOL_MAJOR = 6;
/**
- * Constant used to identify the ToolMinor axis of a motion event.
+ * Axis constant: ToolMinor axis of a motion event.
* <p>
* <ul>
* <li>For a touch screen, reports the length of the minor axis of an ellipse that
@@ -525,7 +608,7 @@ public final class MotionEvent extends InputEvent implements Parcelable {
public static final int AXIS_TOOL_MINOR = 7;
/**
- * Constant used to identify the Orientation axis of a motion event.
+ * Axis constant: Orientation axis of a motion event.
* <p>
* <ul>
* <li>For a touch screen or touch pad, reports the orientation of the finger
@@ -547,7 +630,7 @@ public final class MotionEvent extends InputEvent implements Parcelable {
public static final int AXIS_ORIENTATION = 8;
/**
- * Constant used to identify the Vertical Scroll axis of a motion event.
+ * Axis constant: Vertical Scroll axis of a motion event.
* <p>
* <ul>
* <li>For a mouse, reports the relative movement of the vertical scroll wheel.
@@ -565,7 +648,7 @@ public final class MotionEvent extends InputEvent implements Parcelable {
public static final int AXIS_VSCROLL = 9;
/**
- * Constant used to identify the Horizontal Scroll axis of a motion event.
+ * Axis constant: Horizontal Scroll axis of a motion event.
* <p>
* <ul>
* <li>For a mouse, reports the relative movement of the horizontal scroll wheel.
@@ -583,7 +666,7 @@ public final class MotionEvent extends InputEvent implements Parcelable {
public static final int AXIS_HSCROLL = 10;
/**
- * Constant used to identify the Z axis of a motion event.
+ * Axis constant: Z axis of a motion event.
* <p>
* <ul>
* <li>For a joystick, reports the absolute Z position of the joystick.
@@ -601,7 +684,7 @@ public final class MotionEvent extends InputEvent implements Parcelable {
public static final int AXIS_Z = 11;
/**
- * Constant used to identify the X Rotation axis of a motion event.
+ * Axis constant: X Rotation axis of a motion event.
* <p>
* <ul>
* <li>For a joystick, reports the absolute rotation angle about the X axis.
@@ -617,7 +700,7 @@ public final class MotionEvent extends InputEvent implements Parcelable {
public static final int AXIS_RX = 12;
/**
- * Constant used to identify the Y Rotation axis of a motion event.
+ * Axis constant: Y Rotation axis of a motion event.
* <p>
* <ul>
* <li>For a joystick, reports the absolute rotation angle about the Y axis.
@@ -633,7 +716,7 @@ public final class MotionEvent extends InputEvent implements Parcelable {
public static final int AXIS_RY = 13;
/**
- * Constant used to identify the Z Rotation axis of a motion event.
+ * Axis constant: Z Rotation axis of a motion event.
* <p>
* <ul>
* <li>For a joystick, reports the absolute rotation angle about the Z axis.
@@ -651,7 +734,7 @@ public final class MotionEvent extends InputEvent implements Parcelable {
public static final int AXIS_RZ = 14;
/**
- * Constant used to identify the Hat X axis of a motion event.
+ * Axis constant: Hat X axis of a motion event.
* <p>
* <ul>
* <li>For a joystick, reports the absolute X position of the directional hat control.
@@ -667,7 +750,7 @@ public final class MotionEvent extends InputEvent implements Parcelable {
public static final int AXIS_HAT_X = 15;
/**
- * Constant used to identify the Hat Y axis of a motion event.
+ * Axis constant: Hat Y axis of a motion event.
* <p>
* <ul>
* <li>For a joystick, reports the absolute Y position of the directional hat control.
@@ -683,7 +766,7 @@ public final class MotionEvent extends InputEvent implements Parcelable {
public static final int AXIS_HAT_Y = 16;
/**
- * Constant used to identify the Left Trigger axis of a motion event.
+ * Axis constant: Left Trigger axis of a motion event.
* <p>
* <ul>
* <li>For a joystick, reports the absolute position of the left trigger control.
@@ -699,7 +782,7 @@ public final class MotionEvent extends InputEvent implements Parcelable {
public static final int AXIS_LTRIGGER = 17;
/**
- * Constant used to identify the Right Trigger axis of a motion event.
+ * Axis constant: Right Trigger axis of a motion event.
* <p>
* <ul>
* <li>For a joystick, reports the absolute position of the right trigger control.
@@ -715,7 +798,7 @@ public final class MotionEvent extends InputEvent implements Parcelable {
public static final int AXIS_RTRIGGER = 18;
/**
- * Constant used to identify the Throttle axis of a motion event.
+ * Axis constant: Throttle axis of a motion event.
* <p>
* <ul>
* <li>For a joystick, reports the absolute position of the throttle control.
@@ -731,7 +814,7 @@ public final class MotionEvent extends InputEvent implements Parcelable {
public static final int AXIS_THROTTLE = 19;
/**
- * Constant used to identify the Rudder axis of a motion event.
+ * Axis constant: Rudder axis of a motion event.
* <p>
* <ul>
* <li>For a joystick, reports the absolute position of the rudder control.
@@ -747,7 +830,7 @@ public final class MotionEvent extends InputEvent implements Parcelable {
public static final int AXIS_RUDDER = 20;
/**
- * Constant used to identify the Wheel axis of a motion event.
+ * Axis constant: Wheel axis of a motion event.
* <p>
* <ul>
* <li>For a joystick, reports the absolute position of the steering wheel control.
@@ -763,7 +846,7 @@ public final class MotionEvent extends InputEvent implements Parcelable {
public static final int AXIS_WHEEL = 21;
/**
- * Constant used to identify the Gas axis of a motion event.
+ * Axis constant: Gas axis of a motion event.
* <p>
* <ul>
* <li>For a joystick, reports the absolute position of the gas (accelerator) control.
@@ -780,7 +863,7 @@ public final class MotionEvent extends InputEvent implements Parcelable {
public static final int AXIS_GAS = 22;
/**
- * Constant used to identify the Brake axis of a motion event.
+ * Axis constant: Brake axis of a motion event.
* <p>
* <ul>
* <li>For a joystick, reports the absolute position of the brake control.
@@ -796,7 +879,24 @@ public final class MotionEvent extends InputEvent implements Parcelable {
public static final int AXIS_BRAKE = 23;
/**
- * Constant used to identify the Generic 1 axis of a motion event.
+ * Axis constant: Distance axis of a motion event.
+ * <p>
+ * <ul>
+ * <li>For a stylus, reports the distance of the stylus from the screen.
+ * The value is normalized to a range from 0.0 (direct contact) to 1.0 (furthest measurable
+ * distance).
+ * </ul>
+ * </p>
+ *
+ * @see #getAxisValue(int, int)
+ * @see #getHistoricalAxisValue(int, int, int)
+ * @see MotionEvent.PointerCoords#getAxisValue(int)
+ * @see InputDevice#getMotionRange
+ */
+ public static final int AXIS_DISTANCE = 24;
+
+ /**
+ * Axis constant: Generic 1 axis of a motion event.
* The interpretation of a generic axis is device-specific.
*
* @see #getAxisValue(int, int)
@@ -807,7 +907,7 @@ public final class MotionEvent extends InputEvent implements Parcelable {
public static final int AXIS_GENERIC_1 = 32;
/**
- * Constant used to identify the Generic 2 axis of a motion event.
+ * Axis constant: Generic 2 axis of a motion event.
* The interpretation of a generic axis is device-specific.
*
* @see #getAxisValue(int, int)
@@ -818,7 +918,7 @@ public final class MotionEvent extends InputEvent implements Parcelable {
public static final int AXIS_GENERIC_2 = 33;
/**
- * Constant used to identify the Generic 3 axis of a motion event.
+ * Axis constant: Generic 3 axis of a motion event.
* The interpretation of a generic axis is device-specific.
*
* @see #getAxisValue(int, int)
@@ -829,7 +929,7 @@ public final class MotionEvent extends InputEvent implements Parcelable {
public static final int AXIS_GENERIC_3 = 34;
/**
- * Constant used to identify the Generic 4 axis of a motion event.
+ * Axis constant: Generic 4 axis of a motion event.
* The interpretation of a generic axis is device-specific.
*
* @see #getAxisValue(int, int)
@@ -840,7 +940,7 @@ public final class MotionEvent extends InputEvent implements Parcelable {
public static final int AXIS_GENERIC_4 = 35;
/**
- * Constant used to identify the Generic 5 axis of a motion event.
+ * Axis constant: Generic 5 axis of a motion event.
* The interpretation of a generic axis is device-specific.
*
* @see #getAxisValue(int, int)
@@ -851,7 +951,7 @@ public final class MotionEvent extends InputEvent implements Parcelable {
public static final int AXIS_GENERIC_5 = 36;
/**
- * Constant used to identify the Generic 6 axis of a motion event.
+ * Axis constant: Generic 6 axis of a motion event.
* The interpretation of a generic axis is device-specific.
*
* @see #getAxisValue(int, int)
@@ -862,7 +962,7 @@ public final class MotionEvent extends InputEvent implements Parcelable {
public static final int AXIS_GENERIC_6 = 37;
/**
- * Constant used to identify the Generic 7 axis of a motion event.
+ * Axis constant: Generic 7 axis of a motion event.
* The interpretation of a generic axis is device-specific.
*
* @see #getAxisValue(int, int)
@@ -873,7 +973,7 @@ public final class MotionEvent extends InputEvent implements Parcelable {
public static final int AXIS_GENERIC_7 = 38;
/**
- * Constant used to identify the Generic 8 axis of a motion event.
+ * Axis constant: Generic 8 axis of a motion event.
* The interpretation of a generic axis is device-specific.
*
* @see #getAxisValue(int, int)
@@ -884,7 +984,7 @@ public final class MotionEvent extends InputEvent implements Parcelable {
public static final int AXIS_GENERIC_8 = 39;
/**
- * Constant used to identify the Generic 9 axis of a motion event.
+ * Axis constant: Generic 9 axis of a motion event.
* The interpretation of a generic axis is device-specific.
*
* @see #getAxisValue(int, int)
@@ -895,7 +995,7 @@ public final class MotionEvent extends InputEvent implements Parcelable {
public static final int AXIS_GENERIC_9 = 40;
/**
- * Constant used to identify the Generic 10 axis of a motion event.
+ * Axis constant: Generic 10 axis of a motion event.
* The interpretation of a generic axis is device-specific.
*
* @see #getAxisValue(int, int)
@@ -906,7 +1006,7 @@ public final class MotionEvent extends InputEvent implements Parcelable {
public static final int AXIS_GENERIC_10 = 41;
/**
- * Constant used to identify the Generic 11 axis of a motion event.
+ * Axis constant: Generic 11 axis of a motion event.
* The interpretation of a generic axis is device-specific.
*
* @see #getAxisValue(int, int)
@@ -917,7 +1017,7 @@ public final class MotionEvent extends InputEvent implements Parcelable {
public static final int AXIS_GENERIC_11 = 42;
/**
- * Constant used to identify the Generic 12 axis of a motion event.
+ * Axis constant: Generic 12 axis of a motion event.
* The interpretation of a generic axis is device-specific.
*
* @see #getAxisValue(int, int)
@@ -928,7 +1028,7 @@ public final class MotionEvent extends InputEvent implements Parcelable {
public static final int AXIS_GENERIC_12 = 43;
/**
- * Constant used to identify the Generic 13 axis of a motion event.
+ * Axis constant: Generic 13 axis of a motion event.
* The interpretation of a generic axis is device-specific.
*
* @see #getAxisValue(int, int)
@@ -939,7 +1039,7 @@ public final class MotionEvent extends InputEvent implements Parcelable {
public static final int AXIS_GENERIC_13 = 44;
/**
- * Constant used to identify the Generic 14 axis of a motion event.
+ * Axis constant: Generic 14 axis of a motion event.
* The interpretation of a generic axis is device-specific.
*
* @see #getAxisValue(int, int)
@@ -950,7 +1050,7 @@ public final class MotionEvent extends InputEvent implements Parcelable {
public static final int AXIS_GENERIC_14 = 45;
/**
- * Constant used to identify the Generic 15 axis of a motion event.
+ * Axis constant: Generic 15 axis of a motion event.
* The interpretation of a generic axis is device-specific.
*
* @see #getAxisValue(int, int)
@@ -961,7 +1061,7 @@ public final class MotionEvent extends InputEvent implements Parcelable {
public static final int AXIS_GENERIC_15 = 46;
/**
- * Constant used to identify the Generic 16 axis of a motion event.
+ * Axis constant: Generic 16 axis of a motion event.
* The interpretation of a generic axis is device-specific.
*
* @see #getAxisValue(int, int)
@@ -977,7 +1077,7 @@ public final class MotionEvent extends InputEvent implements Parcelable {
// Symbolic names of all axes.
private static final SparseArray<String> AXIS_SYMBOLIC_NAMES = new SparseArray<String>();
- private static void populateAxisSymbolicNames() {
+ static {
SparseArray<String> names = AXIS_SYMBOLIC_NAMES;
names.append(AXIS_X, "AXIS_X");
names.append(AXIS_Y, "AXIS_Y");
@@ -1003,6 +1103,7 @@ public final class MotionEvent extends InputEvent implements Parcelable {
names.append(AXIS_WHEEL, "AXIS_WHEEL");
names.append(AXIS_GAS, "AXIS_GAS");
names.append(AXIS_BRAKE, "AXIS_BRAKE");
+ names.append(AXIS_DISTANCE, "AXIS_DISTANCE");
names.append(AXIS_GENERIC_1, "AXIS_GENERIC_1");
names.append(AXIS_GENERIC_2, "AXIS_GENERIC_2");
names.append(AXIS_GENERIC_3, "AXIS_GENERIC_3");
@@ -1021,8 +1122,169 @@ public final class MotionEvent extends InputEvent implements Parcelable {
names.append(AXIS_GENERIC_16, "AXIS_GENERIC_16");
}
+ /**
+ * Button constant: Primary button (left mouse button, stylus tip).
+ *
+ * @see #getButtonState
+ */
+ public static final int BUTTON_PRIMARY = 1 << 0;
+
+ /**
+ * Button constant: Secondary button (right mouse button, stylus barrel).
+ *
+ * @see #getButtonState
+ */
+ public static final int BUTTON_SECONDARY = 1 << 1;
+
+ /**
+ * Button constant: Tertiary button (middle mouse button).
+ *
+ * @see #getButtonState
+ */
+ public static final int BUTTON_TERTIARY = 1 << 2;
+
+ /**
+ * Button constant: Back button pressed (mouse back button).
+ * <p>
+ * The system may send a {@link KeyEvent#KEYCODE_BACK} key press to the application
+ * when this button is pressed.
+ * </p>
+ *
+ * @see #getButtonState
+ */
+ public static final int BUTTON_BACK = 1 << 3;
+
+ /**
+ * Button constant: Forward button pressed (mouse forward button).
+ * <p>
+ * The system may send a {@link KeyEvent#KEYCODE_FORWARD} key press to the application
+ * when this button is pressed.
+ * </p>
+ *
+ * @see #getButtonState
+ */
+ public static final int BUTTON_FORWARD = 1 << 4;
+
+ /**
+ * Button constant: Eraser button pressed (stylus end).
+ *
+ * @see #getButtonState
+ */
+ public static final int BUTTON_ERASER = 1 << 5;
+
+ // NOTE: If you add a new axis here you must also add it to:
+ // native/include/android/input.h
+
+ // Symbolic names of all button states in bit order from least significant
+ // to most significant.
+ private static final String[] BUTTON_SYMBOLIC_NAMES = new String[] {
+ "BUTTON_PRIMARY",
+ "BUTTON_SECONDARY",
+ "BUTTON_TERTIARY",
+ "BUTTON_BACK",
+ "BUTTON_FORWARD",
+ "BUTTON_ERASER",
+ "0x00000040",
+ "0x00000080",
+ "0x00000100",
+ "0x00000200",
+ "0x00000400",
+ "0x00000800",
+ "0x00001000",
+ "0x00002000",
+ "0x00004000",
+ "0x00008000",
+ "0x00010000",
+ "0x00020000",
+ "0x00040000",
+ "0x00080000",
+ "0x00100000",
+ "0x00200000",
+ "0x00400000",
+ "0x00800000",
+ "0x01000000",
+ "0x02000000",
+ "0x04000000",
+ "0x08000000",
+ "0x10000000",
+ "0x20000000",
+ "0x40000000",
+ "0x80000000",
+ };
+
+ /**
+ * Tool type constant: Unknown tool type.
+ * This constant is used when the tool type is not known or is not relevant,
+ * such as for a trackball or other non-pointing device.
+ *
+ * @see #getToolType
+ */
+ public static final int TOOL_TYPE_UNKNOWN = 0;
+
+ /**
+ * Tool type constant: The tool is a finger directly touching the display.
+ *
+ * This is a <em>direct</em> positioning tool.
+ *
+ * @see #getToolType
+ */
+ public static final int TOOL_TYPE_FINGER = 1;
+
+ /**
+ * Tool type constant: The tool is a stylus directly touching the display
+ * or hovering slightly above it.
+ *
+ * This is a <em>direct</em> positioning tool.
+ *
+ * @see #getToolType
+ */
+ public static final int TOOL_TYPE_STYLUS = 2;
+
+ /**
+ * Tool type constant: The tool is a mouse or trackpad that translates
+ * relative motions into cursor movements on the display.
+ *
+ * This is an <em>indirect</em> positioning tool.
+ *
+ * @see #getToolType
+ */
+ public static final int TOOL_TYPE_MOUSE = 3;
+
+ /**
+ * Tool type constant: The tool is a finger on a touch pad that is not
+ * directly attached to the display. Finger movements on the touch pad
+ * may be translated into touches on the display, possibly with visual feedback.
+ *
+ * This is an <em>indirect</em> positioning tool.
+ *
+ * @see #getToolType
+ */
+ public static final int TOOL_TYPE_INDIRECT_FINGER = 4;
+
+ /**
+ * Tool type constant: The tool is a stylus on a digitizer tablet that is not
+ * attached to the display. Stylus movements on the digitizer may be translated
+ * into touches on the display, possibly with visual feedback.
+ *
+ * This is an <em>indirect</em> positioning tool.
+ *
+ * @see #getToolType
+ */
+ public static final int TOOL_TYPE_INDIRECT_STYLUS = 5;
+
+ // NOTE: If you add a new tool type here you must also add it to:
+ // native/include/android/input.h
+
+ // Symbolic names of all tool types.
+ private static final SparseArray<String> TOOL_TYPE_SYMBOLIC_NAMES = new SparseArray<String>();
static {
- populateAxisSymbolicNames();
+ SparseArray<String> names = TOOL_TYPE_SYMBOLIC_NAMES;
+ names.append(TOOL_TYPE_UNKNOWN, "TOOL_TYPE_UNKNOWN");
+ names.append(TOOL_TYPE_FINGER, "TOOL_TYPE_FINGER");
+ names.append(TOOL_TYPE_STYLUS, "TOOL_TYPE_STYLUS");
+ names.append(TOOL_TYPE_MOUSE, "TOOL_TYPE_MOUSE");
+ names.append(TOOL_TYPE_INDIRECT_FINGER, "TOOL_TYPE_INDIRECT_FINGER");
+ names.append(TOOL_TYPE_INDIRECT_STYLUS, "TOOL_TYPE_INDIRECT_STYLUS");
}
// Private value for history pos that obtains the current sample.
@@ -1035,10 +1297,23 @@ public final class MotionEvent extends InputEvent implements Parcelable {
// Shared temporary objects used when translating coordinates supplied by
// the caller into single element PointerCoords and pointer id arrays.
- // Must lock gTmpPointerCoords prior to use.
- private static final PointerCoords[] gTmpPointerCoords =
- new PointerCoords[] { new PointerCoords() };
- private static final int[] gTmpPointerIds = new int[] { 0 /*always 0*/ };
+ private static final Object gSharedTempLock = new Object();
+ private static PointerCoords[] gSharedTempPointerCoords;
+ private static PointerProperties[] gSharedTempPointerProperties;
+ private static int[] gSharedTempPointerIndexMap;
+
+ private static final void ensureSharedTempPointerCapacity(int desiredCapacity) {
+ if (gSharedTempPointerCoords == null
+ || gSharedTempPointerCoords.length < desiredCapacity) {
+ int capacity = gSharedTempPointerCoords != null ? gSharedTempPointerCoords.length : 8;
+ while (capacity < desiredCapacity) {
+ capacity *= 2;
+ }
+ gSharedTempPointerCoords = PointerCoords.createArray(capacity);
+ gSharedTempPointerProperties = PointerProperties.createArray(capacity);
+ gSharedTempPointerIndexMap = new int[capacity];
+ }
+ }
// Pointer to the native MotionEvent object that contains the actual data.
private int mNativePtr;
@@ -1048,10 +1323,11 @@ public final class MotionEvent extends InputEvent implements Parcelable {
private boolean mRecycled;
private static native int nativeInitialize(int nativePtr,
- int deviceId, int source, int action, int flags, int edgeFlags, int metaState,
+ int deviceId, int source, int action, int flags, int edgeFlags,
+ int metaState, int buttonState,
float xOffset, float yOffset, float xPrecision, float yPrecision,
long downTimeNanos, long eventTimeNanos,
- int pointerCount, int[] pointerIds, PointerCoords[] pointerCoords);
+ int pointerCount, PointerProperties[] pointerIds, PointerCoords[] pointerCoords);
private static native int nativeCopy(int destNativePtr, int sourceNativePtr,
boolean keepHistory);
private static native void nativeDispose(int nativePtr);
@@ -1069,13 +1345,18 @@ public final class MotionEvent extends InputEvent implements Parcelable {
private static native int nativeGetEdgeFlags(int nativePtr);
private static native void nativeSetEdgeFlags(int nativePtr, int action);
private static native int nativeGetMetaState(int nativePtr);
+ private static native int nativeGetButtonState(int nativePtr);
private static native void nativeOffsetLocation(int nativePtr, float deltaX, float deltaY);
+ private static native float nativeGetXOffset(int nativePtr);
+ private static native float nativeGetYOffset(int nativePtr);
private static native float nativeGetXPrecision(int nativePtr);
private static native float nativeGetYPrecision(int nativePtr);
private static native long nativeGetDownTimeNanos(int nativePtr);
+ private static native void nativeSetDownTimeNanos(int nativePtr, long downTime);
private static native int nativeGetPointerCount(int nativePtr);
private static native int nativeGetPointerId(int nativePtr, int pointerIndex);
+ private static native int nativeGetToolType(int nativePtr, int pointerIndex);
private static native int nativeFindPointerIndex(int nativePtr, int pointerId);
private static native int nativeGetHistorySize(int nativePtr);
@@ -1086,6 +1367,8 @@ public final class MotionEvent extends InputEvent implements Parcelable {
int axis, int pointerIndex, int historyPos);
private static native void nativeGetPointerCoords(int nativePtr,
int pointerIndex, int historyPos, PointerCoords outPointerCoords);
+ private static native void nativeGetPointerProperties(int nativePtr,
+ int pointerIndex, PointerProperties outPointerProperties);
private static native void nativeScale(int nativePtr, float scale);
private static native void nativeTransform(int nativePtr, Matrix matrix);
@@ -1127,19 +1410,21 @@ public final class MotionEvent extends InputEvent implements Parcelable {
/**
* Create a new MotionEvent, filling in all of the basic values that
* define the motion.
- *
+ *
* @param downTime The time (in ms) when the user originally pressed down to start
* a stream of position events. This must be obtained from {@link SystemClock#uptimeMillis()}.
* @param eventTime The the time (in ms) when this specific event was generated. This
* must be obtained from {@link SystemClock#uptimeMillis()}.
* @param action The kind of action being performed, such as {@link #ACTION_DOWN}.
- * @param pointers The number of points that will be in this event.
- * @param pointerIds An array of <em>pointers</em> values providing
- * an identifier for each pointer.
- * @param pointerCoords An array of <em>pointers</em> values providing
+ * @param pointerCount The number of pointers that will be in this event.
+ * @param pointerProperties An array of <em>pointerCount</em> values providing
+ * a {@link PointerProperties} property object for each pointer, which must
+ * include the pointer identifier.
+ * @param pointerCoords An array of <em>pointerCount</em> values providing
* a {@link PointerCoords} coordinate object for each pointer.
* @param metaState The state of any meta / modifier keys that were in effect when
* the event was generated.
+ * @param buttonState The state of buttons that are pressed.
* @param xPrecision The precision of the X coordinate being reported.
* @param yPrecision The precision of the Y coordinate being reported.
* @param deviceId The id for the device that this event came from. An id of
@@ -1151,21 +1436,69 @@ public final class MotionEvent extends InputEvent implements Parcelable {
* @param flags The motion event flags.
*/
static public MotionEvent obtain(long downTime, long eventTime,
- int action, int pointers, int[] pointerIds, PointerCoords[] pointerCoords,
- int metaState, float xPrecision, float yPrecision, int deviceId,
+ int action, int pointerCount, PointerProperties[] pointerProperties,
+ PointerCoords[] pointerCoords, int metaState, int buttonState,
+ float xPrecision, float yPrecision, int deviceId,
int edgeFlags, int source, int flags) {
MotionEvent ev = obtain();
ev.mNativePtr = nativeInitialize(ev.mNativePtr,
- deviceId, source, action, flags, edgeFlags, metaState,
+ deviceId, source, action, flags, edgeFlags, metaState, buttonState,
0, 0, xPrecision, yPrecision,
downTime * NS_PER_MS, eventTime * NS_PER_MS,
- pointers, pointerIds, pointerCoords);
+ pointerCount, pointerProperties, pointerCoords);
return ev;
}
/**
* Create a new MotionEvent, filling in all of the basic values that
* define the motion.
+ *
+ * @param downTime The time (in ms) when the user originally pressed down to start
+ * a stream of position events. This must be obtained from {@link SystemClock#uptimeMillis()}.
+ * @param eventTime The the time (in ms) when this specific event was generated. This
+ * must be obtained from {@link SystemClock#uptimeMillis()}.
+ * @param action The kind of action being performed, such as {@link #ACTION_DOWN}.
+ * @param pointerCount The number of pointers that will be in this event.
+ * @param pointerIds An array of <em>pointerCount</em> values providing
+ * an identifier for each pointer.
+ * @param pointerCoords An array of <em>pointerCount</em> values providing
+ * a {@link PointerCoords} coordinate object for each pointer.
+ * @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.
+ * @param yPrecision The precision of the Y coordinate being reported.
+ * @param deviceId The id for the device that this event came from. An id of
+ * zero indicates that the event didn't come from a physical device; other
+ * numbers are arbitrary and you shouldn't depend on the values.
+ * @param edgeFlags A bitfield indicating which edges, if any, were touched by this
+ * MotionEvent.
+ * @param source The source of this event.
+ * @param flags The motion event flags.
+ *
+ * @deprecated Use {@link #obtain(long, long, int, int, PointerProperties[], PointerCoords[], int, int, float, float, int, int, int, int)}
+ * instead.
+ */
+ @Deprecated
+ static public MotionEvent obtain(long downTime, long eventTime,
+ int action, int pointerCount, int[] pointerIds, PointerCoords[] pointerCoords,
+ int metaState, float xPrecision, float yPrecision, int deviceId,
+ int edgeFlags, int source, int flags) {
+ synchronized (gSharedTempLock) {
+ ensureSharedTempPointerCapacity(pointerCount);
+ final PointerProperties[] pp = gSharedTempPointerProperties;
+ for (int i = 0; i < pointerCount; i++) {
+ pp[i].clear();
+ pp[i].id = pointerIds[i];
+ }
+ return obtain(downTime, eventTime, action, pointerCount, pp,
+ pointerCoords, metaState, 0, xPrecision, yPrecision, deviceId,
+ edgeFlags, source, flags);
+ }
+ }
+
+ /**
+ * Create a new MotionEvent, filling in all of the basic values that
+ * define the motion.
*
* @param downTime The time (in ms) when the user originally pressed down to start
* a stream of position events. This must be obtained from {@link SystemClock#uptimeMillis()}.
@@ -1195,20 +1528,25 @@ public final class MotionEvent extends InputEvent implements Parcelable {
static public MotionEvent obtain(long downTime, long eventTime, int action,
float x, float y, float pressure, float size, int metaState,
float xPrecision, float yPrecision, int deviceId, int edgeFlags) {
- synchronized (gTmpPointerCoords) {
- final PointerCoords pc = gTmpPointerCoords[0];
- pc.clear();
- pc.x = x;
- pc.y = y;
- pc.pressure = pressure;
- pc.size = size;
-
- MotionEvent ev = obtain();
+ MotionEvent ev = obtain();
+ synchronized (gSharedTempLock) {
+ ensureSharedTempPointerCapacity(1);
+ final PointerProperties[] pp = gSharedTempPointerProperties;
+ pp[0].clear();
+ pp[0].id = 0;
+
+ final PointerCoords pc[] = gSharedTempPointerCoords;
+ pc[0].clear();
+ pc[0].x = x;
+ pc[0].y = y;
+ pc[0].pressure = pressure;
+ pc[0].size = size;
+
ev.mNativePtr = nativeInitialize(ev.mNativePtr,
- deviceId, InputDevice.SOURCE_UNKNOWN, action, 0, edgeFlags, metaState,
+ deviceId, InputDevice.SOURCE_UNKNOWN, action, 0, edgeFlags, metaState, 0,
0, 0, xPrecision, yPrecision,
downTime * NS_PER_MS, eventTime * NS_PER_MS,
- 1, gTmpPointerIds, gTmpPointerCoords);
+ 1, pp, pc);
return ev;
}
}
@@ -1222,7 +1560,7 @@ public final class MotionEvent extends InputEvent implements Parcelable {
* @param eventTime The the time (in ms) when this specific event was generated. This
* must be obtained from {@link SystemClock#uptimeMillis()}.
* @param action The kind of action being performed, such as {@link #ACTION_DOWN}.
- * @param pointers The number of pointers that are active in this event.
+ * @param pointerCount The number of pointers that are active in this event.
* @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
@@ -1248,7 +1586,7 @@ public final class MotionEvent extends InputEvent implements Parcelable {
*/
@Deprecated
static public MotionEvent obtain(long downTime, long eventTime, int action,
- int pointers, float x, float y, float pressure, float size, int metaState,
+ int pointerCount, float x, float y, float pressure, float size, int metaState,
float xPrecision, float yPrecision, int deviceId, int edgeFlags) {
return obtain(downTime, eventTime, action, x, y, pressure, size,
metaState, xPrecision, yPrecision, deviceId, edgeFlags);
@@ -1444,6 +1782,16 @@ public final class MotionEvent extends InputEvent implements Parcelable {
}
/**
+ * Sets the time (in ms) when the user originally pressed down to start
+ * a stream of position events.
+ *
+ * @hide
+ */
+ public final void setDownTime(long downTime) {
+ nativeSetDownTimeNanos(mNativePtr, downTime * NS_PER_MS);
+ }
+
+ /**
* Returns the time (in ms) when this specific event was generated.
*/
public final long getEventTime() {
@@ -1582,7 +1930,27 @@ public final class MotionEvent extends InputEvent implements Parcelable {
public final int getPointerId(int pointerIndex) {
return nativeGetPointerId(mNativePtr, pointerIndex);
}
-
+
+ /**
+ * Gets the tool type of a pointer for the given pointer index.
+ * The tool type indicates the type of tool used to make contact such
+ * as a finger or stylus, if known.
+ *
+ * @param pointerIndex Raw index of pointer to retrieve. Value may be from 0
+ * (the first pointer that is down) to {@link #getPointerCount()}-1.
+ * @return The tool type of the pointer.
+ *
+ * @see #TOOL_TYPE_UNKNOWN
+ * @see #TOOL_TYPE_FINGER
+ * @see #TOOL_TYPE_STYLUS
+ * @see #TOOL_TYPE_MOUSE
+ * @see #TOOL_TYPE_INDIRECT_FINGER
+ * @see #TOOL_TYPE_INDIRECT_STYLUS
+ */
+ public final int getToolType(int pointerIndex) {
+ return nativeGetToolType(mNativePtr, pointerIndex);
+ }
+
/**
* Given a pointer identifier, find the index of its data in the event.
*
@@ -1594,7 +1962,7 @@ public final class MotionEvent extends InputEvent implements Parcelable {
public final int findPointerIndex(int pointerId) {
return nativeFindPointerIndex(mNativePtr, pointerId);
}
-
+
/**
* Returns the X coordinate of this event for the given pointer
* <em>index</em> (use {@link #getPointerId(int)} to find the pointer
@@ -1770,6 +2138,21 @@ public final class MotionEvent extends InputEvent implements Parcelable {
}
/**
+ * Populates a {@link PointerProperties} object with pointer properties for
+ * the specified pointer index.
+ *
+ * @param pointerIndex Raw index of pointer to retrieve. Value may be from 0
+ * (the first pointer that is down) to {@link #getPointerCount()}-1.
+ * @param outPointerProperties The pointer properties object to populate.
+ *
+ * @see PointerProperties
+ */
+ public final void getPointerProperties(int pointerIndex,
+ PointerProperties outPointerProperties) {
+ nativeGetPointerProperties(mNativePtr, pointerIndex, outPointerProperties);
+ }
+
+ /**
* Returns the state of any meta / modifier keys that were in effect when
* the event was generated. This is the same values as those
* returned by {@link KeyEvent#getMetaState() KeyEvent.getMetaState}.
@@ -1784,6 +2167,22 @@ public final class MotionEvent extends InputEvent implements Parcelable {
}
/**
+ * Gets the state of all buttons that are pressed such as a mouse or stylus button.
+ *
+ * @return The button state.
+ *
+ * @see #BUTTON_PRIMARY
+ * @see #BUTTON_SECONDARY
+ * @see #BUTTON_TERTIARY
+ * @see #BUTTON_FORWARD
+ * @see #BUTTON_BACK
+ * @see #BUTTON_ERASER
+ */
+ public final int getButtonState() {
+ return nativeGetButtonState(mNativePtr);
+ }
+
+ /**
* Returns the original raw X coordinate of this event. For touch
* events on the screen, this is the original location of the event
* on the screen, before it had been adjusted for the containing window
@@ -2297,14 +2696,16 @@ public final class MotionEvent extends InputEvent implements Parcelable {
*/
public final void addBatch(long eventTime, float x, float y,
float pressure, float size, int metaState) {
- synchronized (gTmpPointerCoords) {
- final PointerCoords pc = gTmpPointerCoords[0];
- pc.clear();
- pc.x = x;
- pc.y = y;
- pc.pressure = pressure;
- pc.size = size;
- nativeAddBatch(mNativePtr, eventTime * NS_PER_MS, gTmpPointerCoords, metaState);
+ synchronized (gSharedTempLock) {
+ ensureSharedTempPointerCapacity(1);
+ final PointerCoords[] pc = gSharedTempPointerCoords;
+ pc[0].clear();
+ pc[0].x = x;
+ pc[0].y = y;
+ pc[0].pressure = pressure;
+ pc[0].size = size;
+
+ nativeAddBatch(mNativePtr, eventTime * NS_PER_MS, pc, metaState);
}
}
@@ -2323,30 +2724,187 @@ public final class MotionEvent extends InputEvent implements Parcelable {
nativeAddBatch(mNativePtr, eventTime * NS_PER_MS, pointerCoords, metaState);
}
+ /**
+ * Returns true if all points in the motion event are completely within the specified bounds.
+ * @hide
+ */
+ public final boolean isWithinBoundsNoHistory(float left, float top,
+ float right, float bottom) {
+ final int pointerCount = nativeGetPointerCount(mNativePtr);
+ for (int i = 0; i < pointerCount; i++) {
+ final float x = nativeGetAxisValue(mNativePtr, AXIS_X, i, HISTORY_CURRENT);
+ final float y = nativeGetAxisValue(mNativePtr, AXIS_Y, i, HISTORY_CURRENT);
+ if (x < left || x > right || y < top || y > bottom) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private static final float clamp(float value, float low, float high) {
+ if (value < low) {
+ return low;
+ } else if (value > high) {
+ return high;
+ }
+ return value;
+ }
+
+ /**
+ * Returns a new motion events whose points have been clamped to the specified bounds.
+ * @hide
+ */
+ public final MotionEvent clampNoHistory(float left, float top, float right, float bottom) {
+ MotionEvent ev = obtain();
+ synchronized (gSharedTempLock) {
+ final int pointerCount = nativeGetPointerCount(mNativePtr);
+
+ ensureSharedTempPointerCapacity(pointerCount);
+ final PointerProperties[] pp = gSharedTempPointerProperties;
+ final PointerCoords[] pc = gSharedTempPointerCoords;
+
+ for (int i = 0; i < pointerCount; i++) {
+ nativeGetPointerProperties(mNativePtr, i, pp[i]);
+ nativeGetPointerCoords(mNativePtr, i, HISTORY_CURRENT, pc[i]);
+ pc[i].x = clamp(pc[i].x, left, right);
+ pc[i].y = clamp(pc[i].y, top, bottom);
+ }
+ ev.mNativePtr = nativeInitialize(ev.mNativePtr,
+ nativeGetDeviceId(mNativePtr), nativeGetSource(mNativePtr),
+ nativeGetAction(mNativePtr), nativeGetFlags(mNativePtr),
+ nativeGetEdgeFlags(mNativePtr), nativeGetMetaState(mNativePtr),
+ nativeGetButtonState(mNativePtr),
+ nativeGetXOffset(mNativePtr), nativeGetYOffset(mNativePtr),
+ nativeGetXPrecision(mNativePtr), nativeGetYPrecision(mNativePtr),
+ nativeGetDownTimeNanos(mNativePtr),
+ nativeGetEventTimeNanos(mNativePtr, HISTORY_CURRENT),
+ pointerCount, pp, pc);
+ return ev;
+ }
+ }
+
+ /**
+ * Gets an integer where each pointer id present in the event is marked as a bit.
+ * @hide
+ */
+ public final int getPointerIdBits() {
+ int idBits = 0;
+ final int pointerCount = nativeGetPointerCount(mNativePtr);
+ for (int i = 0; i < pointerCount; i++) {
+ idBits |= 1 << nativeGetPointerId(mNativePtr, i);
+ }
+ return idBits;
+ }
+
+ /**
+ * Splits a motion event such that it includes only a subset of pointer ids.
+ * @hide
+ */
+ public final MotionEvent split(int idBits) {
+ MotionEvent ev = obtain();
+ synchronized (gSharedTempLock) {
+ final int oldPointerCount = nativeGetPointerCount(mNativePtr);
+ ensureSharedTempPointerCapacity(oldPointerCount);
+ final PointerProperties[] pp = gSharedTempPointerProperties;
+ final PointerCoords[] pc = gSharedTempPointerCoords;
+ final int[] map = gSharedTempPointerIndexMap;
+
+ final int oldAction = nativeGetAction(mNativePtr);
+ final int oldActionMasked = oldAction & ACTION_MASK;
+ final int oldActionPointerIndex = (oldAction & ACTION_POINTER_INDEX_MASK)
+ >> ACTION_POINTER_INDEX_SHIFT;
+ int newActionPointerIndex = -1;
+ int newPointerCount = 0;
+ int newIdBits = 0;
+ for (int i = 0; i < oldPointerCount; i++) {
+ nativeGetPointerProperties(mNativePtr, i, pp[newPointerCount]);
+ final int idBit = 1 << pp[newPointerCount].id;
+ if ((idBit & idBits) != 0) {
+ if (i == oldActionPointerIndex) {
+ newActionPointerIndex = newPointerCount;
+ }
+ map[newPointerCount] = i;
+ newPointerCount += 1;
+ newIdBits |= idBit;
+ }
+ }
+
+ if (newPointerCount == 0) {
+ throw new IllegalArgumentException("idBits did not match any ids in the event");
+ }
+
+ final int newAction;
+ if (oldActionMasked == ACTION_POINTER_DOWN || oldActionMasked == ACTION_POINTER_UP) {
+ if (newActionPointerIndex < 0) {
+ // An unrelated pointer changed.
+ newAction = ACTION_MOVE;
+ } else if (newPointerCount == 1) {
+ // The first/last pointer went down/up.
+ newAction = oldActionMasked == ACTION_POINTER_DOWN
+ ? ACTION_DOWN : ACTION_UP;
+ } else {
+ // A secondary pointer went down/up.
+ newAction = oldActionMasked
+ | (newActionPointerIndex << ACTION_POINTER_INDEX_SHIFT);
+ }
+ } else {
+ // Simple up/down/cancel/move or other motion action.
+ newAction = oldAction;
+ }
+
+ final int historySize = nativeGetHistorySize(mNativePtr);
+ for (int h = 0; h <= historySize; h++) {
+ final int historyPos = h == historySize ? HISTORY_CURRENT : h;
+
+ for (int i = 0; i < newPointerCount; i++) {
+ nativeGetPointerCoords(mNativePtr, map[i], historyPos, pc[i]);
+ }
+
+ final long eventTimeNanos = nativeGetEventTimeNanos(mNativePtr, historyPos);
+ if (h == 0) {
+ ev.mNativePtr = nativeInitialize(ev.mNativePtr,
+ nativeGetDeviceId(mNativePtr), nativeGetSource(mNativePtr),
+ newAction, nativeGetFlags(mNativePtr),
+ nativeGetEdgeFlags(mNativePtr), nativeGetMetaState(mNativePtr),
+ nativeGetButtonState(mNativePtr),
+ nativeGetXOffset(mNativePtr), nativeGetYOffset(mNativePtr),
+ nativeGetXPrecision(mNativePtr), nativeGetYPrecision(mNativePtr),
+ nativeGetDownTimeNanos(mNativePtr), eventTimeNanos,
+ newPointerCount, pp, pc);
+ } else {
+ nativeAddBatch(ev.mNativePtr, eventTimeNanos, pc, 0);
+ }
+ }
+ return ev;
+ }
+ }
+
@Override
public String toString() {
- return "MotionEvent{" + Integer.toHexString(System.identityHashCode(this))
- + " pointerId=" + getPointerId(0)
- + " action=" + actionToString(getAction())
- + " x=" + getX()
- + " y=" + getY()
- + " pressure=" + getPressure()
- + " size=" + getSize()
- + " touchMajor=" + getTouchMajor()
- + " touchMinor=" + getTouchMinor()
- + " toolMajor=" + getToolMajor()
- + " toolMinor=" + getToolMinor()
- + " orientation=" + getOrientation()
- + " meta=" + KeyEvent.metaStateToString(getMetaState())
- + " pointerCount=" + getPointerCount()
- + " historySize=" + getHistorySize()
- + " flags=0x" + Integer.toHexString(getFlags())
- + " edgeFlags=0x" + Integer.toHexString(getEdgeFlags())
- + " device=" + getDeviceId()
- + " source=0x" + Integer.toHexString(getSource())
- + (getPointerCount() > 1 ?
- " pointerId2=" + getPointerId(1) + " x2=" + getX(1) + " y2=" + getY(1) : "")
- + "}";
+ StringBuilder msg = new StringBuilder();
+ msg.append("MotionEvent { action=").append(actionToString(getAction()));
+
+ final int pointerCount = getPointerCount();
+ for (int i = 0; i < pointerCount; i++) {
+ msg.append(", id[").append(i).append("]=").append(getPointerId(i));
+ msg.append(", x[").append(i).append("]=").append(getX(i));
+ msg.append(", y[").append(i).append("]=").append(getY(i));
+ msg.append(", toolType[").append(i).append("]=").append(
+ toolTypeToString(getToolType(i)));
+ }
+
+ msg.append(", buttonState=").append(KeyEvent.metaStateToString(getButtonState()));
+ msg.append(", metaState=").append(KeyEvent.metaStateToString(getMetaState()));
+ msg.append(", flags=0x").append(Integer.toHexString(getFlags()));
+ msg.append(", edgeFlags=0x").append(Integer.toHexString(getEdgeFlags()));
+ msg.append(", pointerCount=").append(pointerCount);
+ msg.append(", historySize=").append(getHistorySize());
+ msg.append(", eventTime=").append(getEventTime());
+ msg.append(", downTime=").append(getDownTime());
+ msg.append(", deviceId=").append(getDeviceId());
+ msg.append(", source=0x").append(Integer.toHexString(getSource()));
+ msg.append(" }");
+ return msg.toString();
}
/**
@@ -2429,6 +2987,55 @@ public final class MotionEvent extends InputEvent implements Parcelable {
}
}
+ /**
+ * Returns a string that represents the symbolic name of the specified combined
+ * button state flags such as "0", "BUTTON_PRIMARY",
+ * "BUTTON_PRIMARY|BUTTON_SECONDARY" or an equivalent numeric constant such as "0x10000000"
+ * if unknown.
+ *
+ * @param buttonState The button state.
+ * @return The symbolic name of the specified combined button state flags.
+ * @hide
+ */
+ public static String buttonStateToString(int buttonState) {
+ if (buttonState == 0) {
+ return "0";
+ }
+ StringBuilder result = null;
+ int i = 0;
+ while (buttonState != 0) {
+ final boolean isSet = (buttonState & 1) != 0;
+ buttonState >>>= 1; // unsigned shift!
+ if (isSet) {
+ final String name = BUTTON_SYMBOLIC_NAMES[i];
+ if (result == null) {
+ if (buttonState == 0) {
+ return name;
+ }
+ result = new StringBuilder(name);
+ } else {
+ result.append('|');
+ result.append(name);
+ }
+ }
+ i += 1;
+ }
+ return result.toString();
+ }
+
+ /**
+ * Returns a string that represents the symbolic name of the specified tool type
+ * such as "TOOL_TYPE_FINGER" or an equivalent numeric constant such as "42" if unknown.
+ *
+ * @param toolType The tool type.
+ * @return The symbolic name of the specified tool type.
+ * @hide
+ */
+ public static String toolTypeToString(int toolType) {
+ String symbolicName = TOOL_TYPE_SYMBOLIC_NAMES.get(toolType);
+ return symbolicName != null ? symbolicName : Integer.toString(toolType);
+ }
+
public static final Parcelable.Creator<MotionEvent> CREATOR
= new Parcelable.Creator<MotionEvent>() {
public MotionEvent createFromParcel(Parcel in) {
@@ -2456,8 +3063,9 @@ public final class MotionEvent extends InputEvent implements Parcelable {
/**
* Transfer object for pointer coordinates.
*
- * Objects of this type can be used to manufacture new {@link MotionEvent} objects
- * and to query pointer coordinate information in bulk.
+ * Objects of this type can be used to specify the pointer coordinates when
+ * creating new {@link MotionEvent} objects and to query pointer coordinates
+ * in bulk.
*
* Refer to {@link InputDevice} for information about how different kinds of
* input devices and sources represent pointer coordinates.
@@ -2483,6 +3091,15 @@ public final class MotionEvent extends InputEvent implements Parcelable {
copyFrom(other);
}
+ /** @hide */
+ public static PointerCoords[] createArray(int size) {
+ PointerCoords[] array = new PointerCoords[size];
+ for (int i = 0; i < size; i++) {
+ array[i] = new PointerCoords();
+ }
+ return array;
+ }
+
/**
* The X component of the pointer movement.
*
@@ -2743,4 +3360,71 @@ public final class MotionEvent extends InputEvent implements Parcelable {
}
}
}
+
+ /**
+ * Transfer object for pointer properties.
+ *
+ * Objects of this type can be used to specify the pointer id and tool type
+ * when creating new {@link MotionEvent} objects and to query pointer properties in bulk.
+ */
+ public static final class PointerProperties {
+ /**
+ * Creates a pointer properties object with an invalid pointer id.
+ */
+ public PointerProperties() {
+ clear();
+ }
+
+ /**
+ * Creates a pointer properties object as a copy of the contents of
+ * another pointer properties object.
+ * @param other
+ */
+ public PointerProperties(PointerProperties other) {
+ copyFrom(other);
+ }
+
+ /** @hide */
+ public static PointerProperties[] createArray(int size) {
+ PointerProperties[] array = new PointerProperties[size];
+ for (int i = 0; i < size; i++) {
+ array[i] = new PointerProperties();
+ }
+ return array;
+ }
+
+ /**
+ * The pointer id.
+ * Initially set to {@link #INVALID_POINTER_ID} (-1).
+ *
+ * @see MotionEvent#getPointerId(int)
+ */
+ public int id;
+
+ /**
+ * The pointer tool type.
+ * Initially set to 0.
+ *
+ * @see MotionEvent#getToolType(int)
+ */
+ public int toolType;
+
+ /**
+ * Resets the pointer properties to their initial values.
+ */
+ public void clear() {
+ id = INVALID_POINTER_ID;
+ toolType = TOOL_TYPE_UNKNOWN;
+ }
+
+ /**
+ * Copies the contents of another pointer properties object.
+ *
+ * @param other The pointer properties object to copy.
+ */
+ public void copyFrom(PointerProperties other) {
+ id = other.id;
+ toolType = other.toolType;
+ }
+ }
}
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 791ffb9..4ee3a47 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -3173,6 +3173,23 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
}
/**
+ * Performs button-related actions during a touch down event.
+ *
+ * @param event The event.
+ * @return True if the down was consumed.
+ *
+ * @hide
+ */
+ protected boolean performButtonActionOnTouchDown(MotionEvent event) {
+ if ((event.getButtonState() & MotionEvent.BUTTON_SECONDARY) != 0) {
+ if (showContextMenu(event.getX(), event.getY(), event.getMetaState())) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
* Bring up the context menu for this view.
*
* @return Whether a context menu was displayed.
@@ -3182,6 +3199,20 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
}
/**
+ * Bring up the context menu for this view, referring to the item under the specified point.
+ *
+ * @param x The referenced x coordinate.
+ * @param y The referenced y coordinate.
+ * @param metaState The keyboard modifiers that were pressed.
+ * @return Whether a context menu was displayed.
+ *
+ * @hide
+ */
+ public boolean showContextMenu(float x, float y, int metaState) {
+ return showContextMenu();
+ }
+
+ /**
* Start an action mode.
*
* @param callback Callback that will control the lifecycle of the action mode
@@ -5535,6 +5566,10 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
case MotionEvent.ACTION_DOWN:
mHasPerformedLongPress = false;
+ if (performButtonActionOnTouchDown(event)) {
+ break;
+ }
+
// Walk up the hierarchy to determine if we're inside a scrolling container.
boolean isInScrollingContainer = false;
ViewParent p = getParent();
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 35cca4f..f84b33b 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -129,11 +129,6 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
// First touch target in the linked list of touch targets.
private TouchTarget mFirstTouchTarget;
- // Temporary arrays for splitting pointers.
- private int[] mTmpPointerIndexMap;
- private int[] mTmpPointerIds;
- private MotionEvent.PointerCoords[] mTmpPointerCoords;
-
// For debugging only. You can see these in hierarchyviewer.
@SuppressWarnings({"FieldCanBeLocal", "UnusedDeclaration"})
@ViewDebug.ExportedProperty(category = "events")
@@ -1723,141 +1718,38 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
}
// Calculate the number of pointers to deliver.
- final int oldPointerCount = event.getPointerCount();
- int newPointerCount = 0;
- if (desiredPointerIdBits == TouchTarget.ALL_POINTER_IDS) {
- newPointerCount = oldPointerCount;
- } else {
- for (int i = 0; i < oldPointerCount; i++) {
- final int pointerId = event.getPointerId(i);
- final int pointerIdBit = 1 << pointerId;
- if ((pointerIdBit & desiredPointerIdBits) != 0) {
- newPointerCount += 1;
- }
- }
- }
+ final int oldPointerIdBits = event.getPointerIdBits();
+ final int newPointerIdBits = oldPointerIdBits & desiredPointerIdBits;
// If for some reason we ended up in an inconsistent state where it looks like we
// might produce a motion event with no pointers in it, then drop the event.
- if (newPointerCount == 0) {
+ if (newPointerIdBits == 0) {
return false;
}
// If the number of pointers is the same and we don't need to perform any fancy
// irreversible transformations, then we can reuse the motion event for this
// dispatch as long as we are careful to revert any changes we make.
- final boolean reuse = newPointerCount == oldPointerCount
- && (child == null || child.hasIdentityMatrix());
- if (reuse) {
- if (child == null) {
- handled = super.dispatchTouchEvent(event);
- } else {
- final float offsetX = mScrollX - child.mLeft;
- final float offsetY = mScrollY - child.mTop;
- event.offsetLocation(offsetX, offsetY);
-
- handled = child.dispatchTouchEvent(event);
-
- event.offsetLocation(-offsetX, -offsetY);
- }
- return handled;
- }
-
- // Make a copy of the event.
- // If the number of pointers is different, then we need to filter out irrelevant pointers
- // as we make a copy of the motion event.
- MotionEvent transformedEvent;
- if (newPointerCount == oldPointerCount) {
- transformedEvent = MotionEvent.obtain(event);
- } else {
- growTmpPointerArrays(newPointerCount);
- final int[] newPointerIndexMap = mTmpPointerIndexMap;
- final int[] newPointerIds = mTmpPointerIds;
- final MotionEvent.PointerCoords[] newPointerCoords = mTmpPointerCoords;
-
- int newPointerIndex = 0;
- int oldPointerIndex = 0;
- while (newPointerIndex < newPointerCount) {
- final int pointerId = event.getPointerId(oldPointerIndex);
- final int pointerIdBits = 1 << pointerId;
- if ((pointerIdBits & desiredPointerIdBits) != 0) {
- newPointerIndexMap[newPointerIndex] = oldPointerIndex;
- newPointerIds[newPointerIndex] = pointerId;
- if (newPointerCoords[newPointerIndex] == null) {
- newPointerCoords[newPointerIndex] = new MotionEvent.PointerCoords();
- }
-
- newPointerIndex += 1;
- }
- oldPointerIndex += 1;
- }
-
- final int newAction;
- if (cancel) {
- newAction = MotionEvent.ACTION_CANCEL;
- } else {
- final int oldMaskedAction = oldAction & MotionEvent.ACTION_MASK;
- if (oldMaskedAction == MotionEvent.ACTION_POINTER_DOWN
- || oldMaskedAction == MotionEvent.ACTION_POINTER_UP) {
- final int changedPointerId = event.getPointerId(
- (oldAction & MotionEvent.ACTION_POINTER_INDEX_MASK)
- >> MotionEvent.ACTION_POINTER_INDEX_SHIFT);
- final int changedPointerIdBits = 1 << changedPointerId;
- if ((changedPointerIdBits & desiredPointerIdBits) != 0) {
- if (newPointerCount == 1) {
- // The first/last pointer went down/up.
- newAction = oldMaskedAction == MotionEvent.ACTION_POINTER_DOWN
- ? MotionEvent.ACTION_DOWN : MotionEvent.ACTION_UP;
- } else {
- // A secondary pointer went down/up.
- int newChangedPointerIndex = 0;
- while (newPointerIds[newChangedPointerIndex] != changedPointerId) {
- newChangedPointerIndex += 1;
- }
- newAction = oldMaskedAction | (newChangedPointerIndex
- << MotionEvent.ACTION_POINTER_INDEX_SHIFT);
- }
- } else {
- // An unrelated pointer changed.
- newAction = MotionEvent.ACTION_MOVE;
- }
+ // Otherwise we need to make a copy.
+ final MotionEvent transformedEvent;
+ if (newPointerIdBits == oldPointerIdBits) {
+ if (child == null || child.hasIdentityMatrix()) {
+ if (child == null) {
+ handled = super.dispatchTouchEvent(event);
} else {
- // Simple up/down/cancel/move motion action.
- newAction = oldMaskedAction;
- }
- }
+ final float offsetX = mScrollX - child.mLeft;
+ final float offsetY = mScrollY - child.mTop;
+ event.offsetLocation(offsetX, offsetY);
- transformedEvent = null;
- final int historySize = event.getHistorySize();
- for (int historyIndex = 0; historyIndex <= historySize; historyIndex++) {
- for (newPointerIndex = 0; newPointerIndex < newPointerCount; newPointerIndex++) {
- final MotionEvent.PointerCoords c = newPointerCoords[newPointerIndex];
- oldPointerIndex = newPointerIndexMap[newPointerIndex];
- if (historyIndex != historySize) {
- event.getHistoricalPointerCoords(oldPointerIndex, historyIndex, c);
- } else {
- event.getPointerCoords(oldPointerIndex, c);
- }
- }
+ handled = child.dispatchTouchEvent(event);
- final long eventTime;
- if (historyIndex != historySize) {
- eventTime = event.getHistoricalEventTime(historyIndex);
- } else {
- eventTime = event.getEventTime();
- }
-
- if (transformedEvent == null) {
- transformedEvent = MotionEvent.obtain(
- event.getDownTime(), eventTime, newAction,
- newPointerCount, newPointerIds, newPointerCoords,
- event.getMetaState(), event.getXPrecision(), event.getYPrecision(),
- event.getDeviceId(), event.getEdgeFlags(), event.getSource(),
- event.getFlags());
- } else {
- transformedEvent.addBatch(eventTime, newPointerCoords, 0);
+ event.offsetLocation(-offsetX, -offsetY);
}
+ return handled;
}
+ transformedEvent = MotionEvent.obtain(event);
+ } else {
+ transformedEvent = event.split(newPointerIdBits);
}
// Perform any necessary transformations and dispatch.
@@ -1880,36 +1772,6 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
}
/**
- * Enlarge the temporary pointer arrays for splitting pointers.
- * May discard contents (but keeps PointerCoords objects to avoid reallocating them).
- */
- private void growTmpPointerArrays(int desiredCapacity) {
- final MotionEvent.PointerCoords[] oldTmpPointerCoords = mTmpPointerCoords;
- int capacity;
- if (oldTmpPointerCoords != null) {
- capacity = oldTmpPointerCoords.length;
- if (desiredCapacity <= capacity) {
- return;
- }
- } else {
- capacity = 4;
- }
-
- while (capacity < desiredCapacity) {
- capacity *= 2;
- }
-
- mTmpPointerIndexMap = new int[capacity];
- mTmpPointerIds = new int[capacity];
- mTmpPointerCoords = new MotionEvent.PointerCoords[capacity];
-
- if (oldTmpPointerCoords != null) {
- System.arraycopy(oldTmpPointerCoords, 0, mTmpPointerCoords, 0,
- oldTmpPointerCoords.length);
- }
- }
-
- /**
* Enable or disable the splitting of MotionEvents to multiple children during touch event
* dispatch. This behavior is enabled by default for applications that target an
* SDK version of {@link Build.VERSION_CODES#HONEYCOMB} or newer.
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index df4c4ed..f4300a5 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -2533,6 +2533,21 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
return mContextMenuInfo;
}
+ /** @hide */
+ @Override
+ public boolean showContextMenu(float x, float y, int metaState) {
+ final int position = pointToPosition((int)x, (int)y);
+ if (position != INVALID_POSITION) {
+ final long id = mAdapter.getItemId(position);
+ View child = getChildAt(position - mFirstPosition);
+ if (child != null) {
+ mContextMenuInfo = createContextMenuInfo(child, position, id);
+ return super.showContextMenuForChild(AbsListView.this);
+ }
+ }
+ return super.showContextMenu(x, y, metaState);
+ }
+
@Override
public boolean showContextMenuForChild(View originalView) {
final int longPressPosition = getPositionForView(originalView);
@@ -2846,6 +2861,12 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
break;
}
}
+
+ if (performButtonActionOnTouchDown(ev)) {
+ if (mTouchMode == TOUCH_MODE_DOWN) {
+ removeCallbacks(mPendingCheckForTap);
+ }
+ }
break;
}
diff --git a/core/java/com/android/internal/widget/PointerLocationView.java b/core/java/com/android/internal/widget/PointerLocationView.java
index c34cb9e..d789584 100644
--- a/core/java/com/android/internal/widget/PointerLocationView.java
+++ b/core/java/com/android/internal/widget/PointerLocationView.java
@@ -320,7 +320,8 @@ public class PointerLocationView extends View {
}
}
- private void logPointerCoords(int action, int index, MotionEvent.PointerCoords coords, int id) {
+ private void logPointerCoords(int action, int index, MotionEvent.PointerCoords coords, int id,
+ int toolType, int buttonState) {
final String prefix;
switch (action & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
@@ -386,26 +387,16 @@ public class PointerLocationView extends View {
.append("deg")
.append(" VScroll=").append(coords.getAxisValue(MotionEvent.AXIS_VSCROLL), 1)
.append(" HScroll=").append(coords.getAxisValue(MotionEvent.AXIS_HSCROLL), 1)
+ .append(" ToolType=").append(MotionEvent.toolTypeToString(toolType))
+ .append(" ButtonState=").append(MotionEvent.buttonStateToString(buttonState))
.toString());
}
public void addPointerEvent(MotionEvent event) {
synchronized (mPointers) {
- int action = event.getAction();
-
- //Log.i(TAG, "Motion: action=0x" + Integer.toHexString(action)
- // + " pointers=" + event.getPointerCount());
-
+ final int action = event.getAction();
int NP = mPointers.size();
-
- //mRect.set(0, 0, getWidth(), mHeaderBottom+1);
- //invalidate(mRect);
- //if (mCurDown) {
- // mRect.set(mCurX-mCurWidth-3, mCurY-mCurWidth-3,
- // mCurX+mCurWidth+3, mCurY+mCurWidth+3);
- //} else {
- // mRect.setEmpty();
- //}
+
if (action == MotionEvent.ACTION_DOWN
|| (action & MotionEvent.ACTION_MASK) == MotionEvent.ACTION_POINTER_DOWN) {
final int index = (action & MotionEvent.ACTION_POINTER_INDEX_MASK)
@@ -456,7 +447,8 @@ public class PointerLocationView extends View {
final PointerCoords coords = ps != null ? ps.mCoords : mHoverCoords;
event.getHistoricalPointerCoords(i, historyPos, coords);
if (mPrintCoords) {
- logPointerCoords(action, i, coords, id);
+ logPointerCoords(action, i, coords, id,
+ event.getToolType(i), event.getButtonState());
}
if (ps != null) {
ps.addTrace(coords.x, coords.y);
@@ -469,7 +461,8 @@ public class PointerLocationView extends View {
final PointerCoords coords = ps != null ? ps.mCoords : mHoverCoords;
event.getPointerCoords(i, coords);
if (mPrintCoords) {
- logPointerCoords(action, i, coords, id);
+ logPointerCoords(action, i, coords, id,
+ event.getToolType(i), event.getButtonState());
}
if (ps != null) {
ps.addTrace(coords.x, coords.y);
@@ -500,12 +493,7 @@ public class PointerLocationView extends View {
ps.addTrace(Float.NaN, Float.NaN);
}
}
-
- //if (mCurDown) {
- // mRect.union(mCurX-mCurWidth-3, mCurY-mCurWidth-3,
- // mCurX+mCurWidth+3, mCurY+mCurWidth+3);
- //}
- //invalidate(mRect);
+
postInvalidate();
}
}
diff --git a/core/jni/android_view_MotionEvent.cpp b/core/jni/android_view_MotionEvent.cpp
index 2ede7ec..fef06b2 100644
--- a/core/jni/android_view_MotionEvent.cpp
+++ b/core/jni/android_view_MotionEvent.cpp
@@ -55,6 +55,11 @@ static struct {
jfieldID orientation;
} gPointerCoordsClassInfo;
+static struct {
+ jfieldID id;
+ jfieldID toolType;
+} gPointerPropertiesClassInfo;
+
// ----------------------------------------------------------------------------
MotionEvent* android_view_MotionEvent_getNativePtr(JNIEnv* env, jobject eventObj) {
@@ -115,17 +120,17 @@ static bool validatePointerCount(JNIEnv* env, jint pointerCount) {
return true;
}
-static bool validatePointerIdsArray(JNIEnv* env, jintArray pointerIdsArray,
+static bool validatePointerPropertiesArray(JNIEnv* env, jobjectArray pointerPropertiesObjArray,
size_t pointerCount) {
- if (!pointerIdsArray) {
+ if (!pointerPropertiesObjArray) {
jniThrowException(env, "java/lang/IllegalArgumentException",
- "pointerIds array must not be null");
+ "pointerProperties array must not be null");
return false;
}
- size_t length = size_t(env->GetArrayLength(pointerIdsArray));
+ size_t length = size_t(env->GetArrayLength(pointerPropertiesObjArray));
if (length < pointerCount) {
jniThrowException(env, "java/lang/IllegalArgumentException",
- "pointerIds array must be large enough to hold all pointers");
+ "pointerProperties array must be large enough to hold all pointers");
return false;
}
return true;
@@ -174,6 +179,15 @@ static bool validatePointerCoords(JNIEnv* env, jobject pointerCoordsObj) {
return true;
}
+static bool validatePointerProperties(JNIEnv* env, jobject pointerPropertiesObj) {
+ if (!pointerPropertiesObj) {
+ jniThrowException(env, "java/lang/IllegalArgumentException",
+ "pointerProperties must not be null");
+ return false;
+ }
+ return true;
+}
+
static void pointerCoordsToNative(JNIEnv* env, jobject pointerCoordsObj,
float xOffset, float yOffset, PointerCoords* outRawPointerCoords) {
outRawPointerCoords->clear();
@@ -300,17 +314,36 @@ static void pointerCoordsFromNative(JNIEnv* env, const PointerCoords* rawPointer
env->SetLongField(outPointerCoordsObj, gPointerCoordsClassInfo.mPackedAxisBits, outBits);
}
+static void pointerPropertiesToNative(JNIEnv* env, jobject pointerPropertiesObj,
+ PointerProperties* outPointerProperties) {
+ outPointerProperties->clear();
+ outPointerProperties->id = env->GetIntField(pointerPropertiesObj,
+ gPointerPropertiesClassInfo.id);
+ outPointerProperties->toolType = env->GetIntField(pointerPropertiesObj,
+ gPointerPropertiesClassInfo.toolType);
+}
+
+static void pointerPropertiesFromNative(JNIEnv* env, const PointerProperties* pointerProperties,
+ jobject outPointerPropertiesObj) {
+ env->SetIntField(outPointerPropertiesObj, gPointerPropertiesClassInfo.id,
+ pointerProperties->id);
+ env->SetIntField(outPointerPropertiesObj, gPointerPropertiesClassInfo.toolType,
+ pointerProperties->toolType);
+}
+
// ----------------------------------------------------------------------------
static jint android_view_MotionEvent_nativeInitialize(JNIEnv* env, jclass clazz,
jint nativePtr,
- jint deviceId, jint source, jint action, jint flags, jint edgeFlags, jint metaState,
+ jint deviceId, jint source, jint action, jint flags, jint edgeFlags,
+ jint metaState, jint buttonState,
jfloat xOffset, jfloat yOffset, jfloat xPrecision, jfloat yPrecision,
jlong downTimeNanos, jlong eventTimeNanos,
- jint pointerCount, jintArray pointerIdsArray, jobjectArray pointerCoordsObjArray) {
+ jint pointerCount, jobjectArray pointerPropertiesObjArray,
+ jobjectArray pointerCoordsObjArray) {
if (!validatePointerCount(env, pointerCount)
- || !validatePointerIdsArray(env, pointerIdsArray, pointerCount)
+ || !validatePointerPropertiesArray(env, pointerPropertiesObjArray, pointerCount)
|| !validatePointerCoordsObjArray(env, pointerCoordsObjArray, pointerCount)) {
return 0;
}
@@ -320,29 +353,37 @@ static jint android_view_MotionEvent_nativeInitialize(JNIEnv* env, jclass clazz,
event = new MotionEvent();
}
+ PointerProperties pointerProperties[pointerCount];
PointerCoords rawPointerCoords[pointerCount];
for (jint i = 0; i < pointerCount; i++) {
+ jobject pointerPropertiesObj = env->GetObjectArrayElement(pointerPropertiesObjArray, i);
+ if (!pointerPropertiesObj) {
+ goto Error;
+ }
+ pointerPropertiesToNative(env, pointerPropertiesObj, &pointerProperties[i]);
+ env->DeleteLocalRef(pointerPropertiesObj);
+
jobject pointerCoordsObj = env->GetObjectArrayElement(pointerCoordsObjArray, i);
if (!pointerCoordsObj) {
jniThrowNullPointerException(env, "pointerCoords");
- if (!nativePtr) {
- delete event;
- }
- return 0;
+ goto Error;
}
pointerCoordsToNative(env, pointerCoordsObj, xOffset, yOffset, &rawPointerCoords[i]);
env->DeleteLocalRef(pointerCoordsObj);
}
- int* pointerIds = static_cast<int*>(env->GetPrimitiveArrayCritical(pointerIdsArray, NULL));
-
- event->initialize(deviceId, source, action, flags, edgeFlags, metaState,
+ event->initialize(deviceId, source, action, flags, edgeFlags, metaState, buttonState,
xOffset, yOffset, xPrecision, yPrecision,
- downTimeNanos, eventTimeNanos, pointerCount, pointerIds, rawPointerCoords);
+ downTimeNanos, eventTimeNanos, pointerCount, pointerProperties, rawPointerCoords);
- env->ReleasePrimitiveArrayCritical(pointerIdsArray, pointerIds, JNI_ABORT);
return reinterpret_cast<jint>(event);
+
+Error:
+ if (!nativePtr) {
+ delete event;
+ }
+ return 0;
}
static jint android_view_MotionEvent_nativeCopy(JNIEnv* env, jclass clazz,
@@ -454,12 +495,30 @@ static jint android_view_MotionEvent_nativeGetMetaState(JNIEnv* env, jclass claz
return event->getMetaState();
}
+static jint android_view_MotionEvent_nativeGetButtonState(JNIEnv* env, jclass clazz,
+ jint nativePtr) {
+ MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
+ return event->getButtonState();
+}
+
static void android_view_MotionEvent_nativeOffsetLocation(JNIEnv* env, jclass clazz,
jint nativePtr, jfloat deltaX, jfloat deltaY) {
MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
return event->offsetLocation(deltaX, deltaY);
}
+static jfloat android_view_MotionEvent_nativeGetXOffset(JNIEnv* env, jclass clazz,
+ jint nativePtr) {
+ MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
+ return event->getXOffset();
+}
+
+static jfloat android_view_MotionEvent_nativeGetYOffset(JNIEnv* env, jclass clazz,
+ jint nativePtr) {
+ MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
+ return event->getYOffset();
+}
+
static jfloat android_view_MotionEvent_nativeGetXPrecision(JNIEnv* env, jclass clazz,
jint nativePtr) {
MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
@@ -478,6 +537,12 @@ static jlong android_view_MotionEvent_nativeGetDownTimeNanos(JNIEnv* env, jclass
return event->getDownTime();
}
+static void android_view_MotionEvent_nativeSetDownTimeNanos(JNIEnv* env, jclass clazz,
+ jint nativePtr, jlong downTimeNanos) {
+ MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
+ event->setDownTime(downTimeNanos);
+}
+
static jint android_view_MotionEvent_nativeGetPointerCount(JNIEnv* env, jclass clazz,
jint nativePtr) {
MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
@@ -494,6 +559,16 @@ static jint android_view_MotionEvent_nativeGetPointerId(JNIEnv* env, jclass claz
return event->getPointerId(pointerIndex);
}
+static jint android_view_MotionEvent_nativeGetToolType(JNIEnv* env, jclass clazz,
+ jint nativePtr, jint pointerIndex) {
+ MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
+ size_t pointerCount = event->getPointerCount();
+ if (!validatePointerIndex(env, pointerIndex, pointerCount)) {
+ return -1;
+ }
+ return event->getToolType(pointerIndex);
+}
+
static jint android_view_MotionEvent_nativeFindPointerIndex(JNIEnv* env, jclass clazz,
jint nativePtr, jint pointerId) {
MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
@@ -581,6 +656,19 @@ static void android_view_MotionEvent_nativeGetPointerCoords(JNIEnv* env, jclass
outPointerCoordsObj);
}
+static void android_view_MotionEvent_nativeGetPointerProperties(JNIEnv* env, jclass clazz,
+ jint nativePtr, jint pointerIndex, jobject outPointerPropertiesObj) {
+ MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
+ size_t pointerCount = event->getPointerCount();
+ if (!validatePointerIndex(env, pointerIndex, pointerCount)
+ || !validatePointerProperties(env, outPointerPropertiesObj)) {
+ return;
+ }
+
+ const PointerProperties* pointerProperties = event->getPointerProperties(pointerIndex);
+ pointerPropertiesFromNative(env, pointerProperties, outPointerPropertiesObj);
+}
+
static void android_view_MotionEvent_nativeScale(JNIEnv* env, jclass clazz,
jint nativePtr, jfloat scale) {
MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
@@ -630,7 +718,8 @@ static void android_view_MotionEvent_nativeWriteToParcel(JNIEnv* env, jclass cla
static JNINativeMethod gMotionEventMethods[] = {
/* name, signature, funcPtr */
{ "nativeInitialize",
- "(IIIIIIIFFFFJJI[I[Landroid/view/MotionEvent$PointerCoords;)I",
+ "(IIIIIIIIFFFFJJI[Landroid/view/MotionEvent$PointerProperties;"
+ "[Landroid/view/MotionEvent$PointerCoords;)I",
(void*)android_view_MotionEvent_nativeInitialize },
{ "nativeCopy",
"(IIZ)I",
@@ -674,9 +763,18 @@ static JNINativeMethod gMotionEventMethods[] = {
{ "nativeGetMetaState",
"(I)I",
(void*)android_view_MotionEvent_nativeGetMetaState },
+ { "nativeGetButtonState",
+ "(I)I",
+ (void*)android_view_MotionEvent_nativeGetButtonState },
{ "nativeOffsetLocation",
"(IFF)V",
(void*)android_view_MotionEvent_nativeOffsetLocation },
+ { "nativeGetXOffset",
+ "(I)F",
+ (void*)android_view_MotionEvent_nativeGetXOffset },
+ { "nativeGetYOffset",
+ "(I)F",
+ (void*)android_view_MotionEvent_nativeGetYOffset },
{ "nativeGetXPrecision",
"(I)F",
(void*)android_view_MotionEvent_nativeGetXPrecision },
@@ -686,12 +784,18 @@ static JNINativeMethod gMotionEventMethods[] = {
{ "nativeGetDownTimeNanos",
"(I)J",
(void*)android_view_MotionEvent_nativeGetDownTimeNanos },
+ { "nativeSetDownTimeNanos",
+ "(IJ)V",
+ (void*)android_view_MotionEvent_nativeSetDownTimeNanos },
{ "nativeGetPointerCount",
"(I)I",
(void*)android_view_MotionEvent_nativeGetPointerCount },
{ "nativeGetPointerId",
"(II)I",
(void*)android_view_MotionEvent_nativeGetPointerId },
+ { "nativeGetToolType",
+ "(II)I",
+ (void*)android_view_MotionEvent_nativeGetToolType },
{ "nativeFindPointerIndex",
"(II)I",
(void*)android_view_MotionEvent_nativeFindPointerIndex },
@@ -710,6 +814,9 @@ static JNINativeMethod gMotionEventMethods[] = {
{ "nativeGetPointerCoords",
"(IIILandroid/view/MotionEvent$PointerCoords;)V",
(void*)android_view_MotionEvent_nativeGetPointerCoords },
+ { "nativeGetPointerProperties",
+ "(IILandroid/view/MotionEvent$PointerProperties;)V",
+ (void*)android_view_MotionEvent_nativeGetPointerProperties },
{ "nativeScale",
"(IF)V",
(void*)android_view_MotionEvent_nativeScale },
@@ -781,6 +888,13 @@ int register_android_view_MotionEvent(JNIEnv* env) {
GET_FIELD_ID(gPointerCoordsClassInfo.orientation, clazz,
"orientation", "F");
+ FIND_CLASS(clazz, "android/view/MotionEvent$PointerProperties");
+
+ GET_FIELD_ID(gPointerPropertiesClassInfo.id, clazz,
+ "id", "I");
+ GET_FIELD_ID(gPointerPropertiesClassInfo.toolType, clazz,
+ "toolType", "I");
+
return 0;
}
diff --git a/include/ui/Input.h b/include/ui/Input.h
index c7ebf56..ba1c6b4 100644
--- a/include/ui/Input.h
+++ b/include/ui/Input.h
@@ -157,14 +157,6 @@ enum {
};
/*
- * Button state.
- */
-enum {
- // Primary button pressed (left mouse button).
- BUTTON_STATE_PRIMARY = 1 << 0,
-};
-
-/*
* Describes the basic configuration of input devices that are present.
*/
struct InputConfiguration {
@@ -235,6 +227,29 @@ private:
};
/*
+ * Pointer property data.
+ */
+struct PointerProperties {
+ // The id of the pointer.
+ int32_t id;
+
+ // The pointer tool type.
+ int32_t toolType;
+
+ inline void clear() {
+ id = -1;
+ toolType = 0;
+ }
+
+ bool operator==(const PointerProperties& other) const;
+ inline bool operator!=(const PointerProperties& other) const {
+ return !(*this == other);
+ }
+
+ void copyFrom(const PointerProperties& other);
+};
+
+/*
* Input events.
*/
class InputEvent : public AInputEvent {
@@ -346,6 +361,8 @@ public:
inline void setMetaState(int32_t metaState) { mMetaState = metaState; }
+ inline int32_t getButtonState() const { return mButtonState; }
+
inline float getXOffset() const { return mXOffset; }
inline float getYOffset() const { return mYOffset; }
@@ -356,9 +373,21 @@ public:
inline nsecs_t getDownTime() const { return mDownTime; }
- inline size_t getPointerCount() const { return mPointerIds.size(); }
+ inline void setDownTime(nsecs_t downTime) { mDownTime = downTime; }
+
+ inline size_t getPointerCount() const { return mPointerProperties.size(); }
- inline int32_t getPointerId(size_t pointerIndex) const { return mPointerIds[pointerIndex]; }
+ inline const PointerProperties* getPointerProperties(size_t pointerIndex) const {
+ return &mPointerProperties[pointerIndex];
+ }
+
+ inline int32_t getPointerId(size_t pointerIndex) const {
+ return mPointerProperties[pointerIndex].id;
+ }
+
+ inline int32_t getToolType(size_t pointerIndex) const {
+ return mPointerProperties[pointerIndex].toolType;
+ }
inline nsecs_t getEventTime() const { return mSampleEventTimes[getHistorySize()]; }
@@ -490,6 +519,7 @@ public:
int32_t flags,
int32_t edgeFlags,
int32_t metaState,
+ int32_t buttonState,
float xOffset,
float yOffset,
float xPrecision,
@@ -497,7 +527,7 @@ public:
nsecs_t downTime,
nsecs_t eventTime,
size_t pointerCount,
- const int32_t* pointerIds,
+ const PointerProperties* pointerProperties,
const PointerCoords* pointerCoords);
void copyFrom(const MotionEvent* other, bool keepHistory);
@@ -523,7 +553,9 @@ public:
}
// Low-level accessors.
- inline const int32_t* getPointerIds() const { return mPointerIds.array(); }
+ inline const PointerProperties* getPointerProperties() const {
+ return mPointerProperties.array();
+ }
inline const nsecs_t* getSampleEventTimes() const { return mSampleEventTimes.array(); }
inline const PointerCoords* getSamplePointerCoords() const {
return mSamplePointerCoords.array();
@@ -534,12 +566,13 @@ protected:
int32_t mFlags;
int32_t mEdgeFlags;
int32_t mMetaState;
+ int32_t mButtonState;
float mXOffset;
float mYOffset;
float mXPrecision;
float mYPrecision;
nsecs_t mDownTime;
- Vector<int32_t> mPointerIds;
+ Vector<PointerProperties> mPointerProperties;
Vector<nsecs_t> mSampleEventTimes;
Vector<PointerCoords> mSamplePointerCoords;
};
diff --git a/include/ui/InputTransport.h b/include/ui/InputTransport.h
index 119db81..95e4447 100644
--- a/include/ui/InputTransport.h
+++ b/include/ui/InputTransport.h
@@ -136,6 +136,7 @@ struct InputMessage {
int32_t action;
int32_t flags;
int32_t metaState;
+ int32_t buttonState;
int32_t edgeFlags;
nsecs_t downTime;
float xOffset;
@@ -143,7 +144,7 @@ struct InputMessage {
float xPrecision;
float yPrecision;
size_t pointerCount;
- int32_t pointerIds[MAX_POINTERS];
+ PointerProperties pointerProperties[MAX_POINTERS];
size_t sampleCount;
SampleData sampleData[0]; // variable length
} motion;
@@ -221,6 +222,7 @@ public:
int32_t flags,
int32_t edgeFlags,
int32_t metaState,
+ int32_t buttonState,
float xOffset,
float yOffset,
float xPrecision,
@@ -228,7 +230,7 @@ public:
nsecs_t downTime,
nsecs_t eventTime,
size_t pointerCount,
- const int32_t* pointerIds,
+ const PointerProperties* pointerProperties,
const PointerCoords* pointerCoords);
/* Appends a motion sample to a motion event unless already consumed.
diff --git a/libs/ui/Input.cpp b/libs/ui/Input.cpp
index d811dd7..1ba38a7 100644
--- a/libs/ui/Input.cpp
+++ b/libs/ui/Input.cpp
@@ -373,6 +373,19 @@ void PointerCoords::copyFrom(const PointerCoords& other) {
}
+// --- PointerProperties ---
+
+bool PointerProperties::operator==(const PointerProperties& other) const {
+ return id == other.id
+ && toolType == other.toolType;
+}
+
+void PointerProperties::copyFrom(const PointerProperties& other) {
+ id = other.id;
+ toolType = other.toolType;
+}
+
+
// --- MotionEvent ---
void MotionEvent::initialize(
@@ -382,6 +395,7 @@ void MotionEvent::initialize(
int32_t flags,
int32_t edgeFlags,
int32_t metaState,
+ int32_t buttonState,
float xOffset,
float yOffset,
float xPrecision,
@@ -389,20 +403,21 @@ void MotionEvent::initialize(
nsecs_t downTime,
nsecs_t eventTime,
size_t pointerCount,
- const int32_t* pointerIds,
+ const PointerProperties* pointerProperties,
const PointerCoords* pointerCoords) {
InputEvent::initialize(deviceId, source);
mAction = action;
mFlags = flags;
mEdgeFlags = edgeFlags;
mMetaState = metaState;
+ mButtonState = buttonState;
mXOffset = xOffset;
mYOffset = yOffset;
mXPrecision = xPrecision;
mYPrecision = yPrecision;
mDownTime = downTime;
- mPointerIds.clear();
- mPointerIds.appendArray(pointerIds, pointerCount);
+ mPointerProperties.clear();
+ mPointerProperties.appendArray(pointerProperties, pointerCount);
mSampleEventTimes.clear();
mSamplePointerCoords.clear();
addSample(eventTime, pointerCoords);
@@ -414,12 +429,13 @@ void MotionEvent::copyFrom(const MotionEvent* other, bool keepHistory) {
mFlags = other->mFlags;
mEdgeFlags = other->mEdgeFlags;
mMetaState = other->mMetaState;
+ mButtonState = other->mButtonState;
mXOffset = other->mXOffset;
mYOffset = other->mYOffset;
mXPrecision = other->mXPrecision;
mYPrecision = other->mYPrecision;
mDownTime = other->mDownTime;
- mPointerIds = other->mPointerIds;
+ mPointerProperties = other->mPointerProperties;
if (keepHistory) {
mSampleEventTimes = other->mSampleEventTimes;
@@ -484,9 +500,9 @@ float MotionEvent::getHistoricalAxisValue(int32_t axis, size_t pointerIndex,
}
ssize_t MotionEvent::findPointerIndex(int32_t pointerId) const {
- size_t pointerCount = mPointerIds.size();
+ size_t pointerCount = mPointerProperties.size();
for (size_t i = 0; i < pointerCount; i++) {
- if (mPointerIds.itemAt(i) == pointerId) {
+ if (mPointerProperties.itemAt(i).id == pointerId) {
return i;
}
}
@@ -583,21 +599,25 @@ status_t MotionEvent::readFromParcel(Parcel* parcel) {
mFlags = parcel->readInt32();
mEdgeFlags = parcel->readInt32();
mMetaState = parcel->readInt32();
+ mButtonState = parcel->readInt32();
mXOffset = parcel->readFloat();
mYOffset = parcel->readFloat();
mXPrecision = parcel->readFloat();
mYPrecision = parcel->readFloat();
mDownTime = parcel->readInt64();
- mPointerIds.clear();
- mPointerIds.setCapacity(pointerCount);
+ mPointerProperties.clear();
+ mPointerProperties.setCapacity(pointerCount);
mSampleEventTimes.clear();
mSampleEventTimes.setCapacity(sampleCount);
mSamplePointerCoords.clear();
mSamplePointerCoords.setCapacity(sampleCount * pointerCount);
for (size_t i = 0; i < pointerCount; i++) {
- mPointerIds.push(parcel->readInt32());
+ mPointerProperties.push();
+ PointerProperties& properties = mPointerProperties.editTop();
+ properties.id = parcel->readInt32();
+ properties.toolType = parcel->readInt32();
}
while (sampleCount-- > 0) {
@@ -614,7 +634,7 @@ status_t MotionEvent::readFromParcel(Parcel* parcel) {
}
status_t MotionEvent::writeToParcel(Parcel* parcel) const {
- size_t pointerCount = mPointerIds.size();
+ size_t pointerCount = mPointerProperties.size();
size_t sampleCount = mSampleEventTimes.size();
parcel->writeInt32(pointerCount);
@@ -626,6 +646,7 @@ status_t MotionEvent::writeToParcel(Parcel* parcel) const {
parcel->writeInt32(mFlags);
parcel->writeInt32(mEdgeFlags);
parcel->writeInt32(mMetaState);
+ parcel->writeInt32(mButtonState);
parcel->writeFloat(mXOffset);
parcel->writeFloat(mYOffset);
parcel->writeFloat(mXPrecision);
@@ -633,7 +654,9 @@ status_t MotionEvent::writeToParcel(Parcel* parcel) const {
parcel->writeInt64(mDownTime);
for (size_t i = 0; i < pointerCount; i++) {
- parcel->writeInt32(mPointerIds.itemAt(i));
+ const PointerProperties& properties = mPointerProperties.itemAt(i);
+ parcel->writeInt32(properties.id);
+ parcel->writeInt32(properties.toolType);
}
const PointerCoords* pc = mSamplePointerCoords.array();
diff --git a/libs/ui/InputTransport.cpp b/libs/ui/InputTransport.cpp
index 93d0d1f..ffdfe66 100644
--- a/libs/ui/InputTransport.cpp
+++ b/libs/ui/InputTransport.cpp
@@ -366,6 +366,7 @@ status_t InputPublisher::publishMotionEvent(
int32_t flags,
int32_t edgeFlags,
int32_t metaState,
+ int32_t buttonState,
float xOffset,
float yOffset,
float xPrecision,
@@ -373,16 +374,17 @@ status_t InputPublisher::publishMotionEvent(
nsecs_t downTime,
nsecs_t eventTime,
size_t pointerCount,
- const int32_t* pointerIds,
+ const PointerProperties* pointerProperties,
const PointerCoords* pointerCoords) {
#if DEBUG_TRANSPORT_ACTIONS
LOGD("channel '%s' publisher ~ publishMotionEvent: deviceId=%d, source=0x%x, "
- "action=0x%x, flags=0x%x, edgeFlags=0x%x, metaState=0x%x, xOffset=%f, yOffset=%f, "
+ "action=0x%x, flags=0x%x, edgeFlags=0x%x, metaState=0x%x, buttonState=0x%x, "
+ "xOffset=%f, yOffset=%f, "
"xPrecision=%f, yPrecision=%f, downTime=%lld, eventTime=%lld, "
"pointerCount=%d",
mChannel->getName().string(),
- deviceId, source, action, flags, edgeFlags, metaState, xOffset, yOffset,
- xPrecision, yPrecision, downTime, eventTime, pointerCount);
+ deviceId, source, action, flags, edgeFlags, metaState, buttonState,
+ xOffset, yOffset, xPrecision, yPrecision, downTime, eventTime, pointerCount);
#endif
if (pointerCount > MAX_POINTERS || pointerCount < 1) {
@@ -400,6 +402,7 @@ status_t InputPublisher::publishMotionEvent(
mSharedMessage->motion.flags = flags;
mSharedMessage->motion.edgeFlags = edgeFlags;
mSharedMessage->motion.metaState = metaState;
+ mSharedMessage->motion.buttonState = buttonState;
mSharedMessage->motion.xOffset = xOffset;
mSharedMessage->motion.yOffset = yOffset;
mSharedMessage->motion.xPrecision = xPrecision;
@@ -411,7 +414,7 @@ status_t InputPublisher::publishMotionEvent(
mSharedMessage->motion.sampleData[0].eventTime = eventTime;
for (size_t i = 0; i < pointerCount; i++) {
- mSharedMessage->motion.pointerIds[i] = pointerIds[i];
+ mSharedMessage->motion.pointerProperties[i].copyFrom(pointerProperties[i]);
mSharedMessage->motion.sampleData[0].coords[i].copyFrom(pointerCoords[i]);
}
@@ -694,6 +697,7 @@ void InputConsumer::populateMotionEvent(MotionEvent* motionEvent) const {
mSharedMessage->motion.flags,
mSharedMessage->motion.edgeFlags,
mSharedMessage->motion.metaState,
+ mSharedMessage->motion.buttonState,
mSharedMessage->motion.xOffset,
mSharedMessage->motion.yOffset,
mSharedMessage->motion.xPrecision,
@@ -701,7 +705,7 @@ void InputConsumer::populateMotionEvent(MotionEvent* motionEvent) const {
mSharedMessage->motion.downTime,
mSharedMessage->motion.sampleData[0].eventTime,
mSharedMessage->motion.pointerCount,
- mSharedMessage->motion.pointerIds,
+ mSharedMessage->motion.pointerProperties,
mSharedMessage->motion.sampleData[0].coords);
size_t sampleCount = mSharedMessage->motion.sampleCount;
diff --git a/libs/ui/tests/InputEvent_test.cpp b/libs/ui/tests/InputEvent_test.cpp
index b77489e..e48d5b7 100644
--- a/libs/ui/tests/InputEvent_test.cpp
+++ b/libs/ui/tests/InputEvent_test.cpp
@@ -232,7 +232,14 @@ const float MotionEventTest::X_OFFSET = 1.0f;
const float MotionEventTest::Y_OFFSET = 1.1f;
void MotionEventTest::initializeEventWithHistory(MotionEvent* event) {
- int32_t pointerIds[] = { 1, 2 };
+ PointerProperties pointerProperties[2];
+ pointerProperties[0].clear();
+ pointerProperties[0].id = 1;
+ pointerProperties[0].toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
+ pointerProperties[1].clear();
+ pointerProperties[1].id = 2;
+ pointerProperties[1].toolType = AMOTION_EVENT_TOOL_TYPE_STYLUS;
+
PointerCoords pointerCoords[2];
pointerCoords[0].clear();
pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 10);
@@ -256,10 +263,10 @@ void MotionEventTest::initializeEventWithHistory(MotionEvent* event) {
pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, 28);
event->initialize(2, AINPUT_SOURCE_TOUCHSCREEN, AMOTION_EVENT_ACTION_MOVE,
AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED,
- AMOTION_EVENT_EDGE_FLAG_TOP, AMETA_ALT_ON,
+ AMOTION_EVENT_EDGE_FLAG_TOP, AMETA_ALT_ON, AMOTION_EVENT_BUTTON_PRIMARY,
X_OFFSET, Y_OFFSET, 2.0f, 2.1f,
ARBITRARY_DOWN_TIME, ARBITRARY_EVENT_TIME,
- 2, pointerIds, pointerCoords);
+ 2, pointerProperties, pointerCoords);
pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 110);
pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 111);
@@ -311,6 +318,7 @@ void MotionEventTest::assertEqualsEventWithHistory(const MotionEvent* event) {
ASSERT_EQ(AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED, event->getFlags());
ASSERT_EQ(AMOTION_EVENT_EDGE_FLAG_TOP, event->getEdgeFlags());
ASSERT_EQ(AMETA_ALT_ON, event->getMetaState());
+ ASSERT_EQ(AMOTION_EVENT_BUTTON_PRIMARY, event->getButtonState());
ASSERT_EQ(X_OFFSET, event->getXOffset());
ASSERT_EQ(Y_OFFSET, event->getYOffset());
ASSERT_EQ(2.0f, event->getXPrecision());
@@ -319,7 +327,9 @@ void MotionEventTest::assertEqualsEventWithHistory(const MotionEvent* event) {
ASSERT_EQ(2U, event->getPointerCount());
ASSERT_EQ(1, event->getPointerId(0));
+ ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, event->getToolType(0));
ASSERT_EQ(2, event->getPointerId(1));
+ ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_STYLUS, event->getToolType(1));
ASSERT_EQ(2U, event->getHistorySize());
@@ -534,19 +544,20 @@ TEST_F(MotionEventTest, Transform) {
const float ROTATION = ARC * 2;
const size_t pointerCount = 11;
- int pointerIds[pointerCount];
+ PointerProperties pointerProperties[pointerCount];
PointerCoords pointerCoords[pointerCount];
for (size_t i = 0; i < pointerCount; i++) {
float angle = float(i * ARC * PI_180);
- pointerIds[i] = i;
+ pointerProperties[i].clear();
+ pointerProperties[i].id = i;
pointerCoords[i].clear();
pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_X, sinf(angle) * RADIUS + 3);
pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_Y, -cosf(angle) * RADIUS + 2);
pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, angle);
}
MotionEvent event;
- event.initialize(0, 0, AMOTION_EVENT_ACTION_MOVE, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, pointerCount, pointerIds, pointerCoords);
+ event.initialize(0, 0, AMOTION_EVENT_ACTION_MOVE, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, pointerCount, pointerProperties, pointerCoords);
float originalRawX = 0 + 3;
float originalRawY = -RADIUS + 2;
diff --git a/libs/ui/tests/InputPublisherAndConsumer_test.cpp b/libs/ui/tests/InputPublisherAndConsumer_test.cpp
index 6e18a4f..fcc4cad 100644
--- a/libs/ui/tests/InputPublisherAndConsumer_test.cpp
+++ b/libs/ui/tests/InputPublisherAndConsumer_test.cpp
@@ -156,13 +156,19 @@ void InputPublisherAndConsumerTest::PublishAndConsumeMotionEvent(
const int32_t flags = AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED;
const int32_t edgeFlags = AMOTION_EVENT_EDGE_FLAG_TOP;
const int32_t metaState = AMETA_ALT_LEFT_ON | AMETA_ALT_ON;
+ const int32_t buttonState = AMOTION_EVENT_BUTTON_PRIMARY;
const float xOffset = -10;
const float yOffset = -20;
const float xPrecision = 0.25;
const float yPrecision = 0.5;
const nsecs_t downTime = 3;
const size_t pointerCount = 3;
- const int32_t pointerIds[pointerCount] = { 2, 0, 1 };
+ PointerProperties pointerProperties[pointerCount];
+ for (size_t i = 0; i < pointerCount; i++) {
+ pointerProperties[i].clear();
+ pointerProperties[i].id = (i + 2) % pointerCount;
+ pointerProperties[i].toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
+ }
Vector<nsecs_t> sampleEventTimes;
Vector<PointerCoords> samplePointerCoords;
@@ -186,8 +192,9 @@ void InputPublisherAndConsumerTest::PublishAndConsumeMotionEvent(
}
status = mPublisher->publishMotionEvent(deviceId, source, action, flags, edgeFlags,
- metaState, xOffset, yOffset, xPrecision, yPrecision,
- downTime, sampleEventTimes[0], pointerCount, pointerIds, samplePointerCoords.array());
+ metaState, buttonState, xOffset, yOffset, xPrecision, yPrecision,
+ downTime, sampleEventTimes[0], pointerCount,
+ pointerProperties, samplePointerCoords.array());
ASSERT_EQ(OK, status)
<< "publisher publishMotionEvent should return OK";
@@ -234,6 +241,7 @@ void InputPublisherAndConsumerTest::PublishAndConsumeMotionEvent(
EXPECT_EQ(flags, motionEvent->getFlags());
EXPECT_EQ(edgeFlags, motionEvent->getEdgeFlags());
EXPECT_EQ(metaState, motionEvent->getMetaState());
+ EXPECT_EQ(buttonState, motionEvent->getButtonState());
EXPECT_EQ(xPrecision, motionEvent->getXPrecision());
EXPECT_EQ(yPrecision, motionEvent->getYPrecision());
EXPECT_EQ(downTime, motionEvent->getDownTime());
@@ -243,7 +251,8 @@ void InputPublisherAndConsumerTest::PublishAndConsumeMotionEvent(
for (size_t i = 0; i < pointerCount; i++) {
SCOPED_TRACE(i);
- EXPECT_EQ(pointerIds[i], motionEvent->getPointerId(i));
+ EXPECT_EQ(pointerProperties[i].id, motionEvent->getPointerId(i));
+ EXPECT_EQ(pointerProperties[i].toolType, motionEvent->getToolType(i));
}
for (size_t sampleIndex = 0; sampleIndex < lastSampleIndex; sampleIndex++) {
@@ -352,17 +361,20 @@ TEST_F(InputPublisherAndConsumerTest, PublishMotionEvent_WhenNotReset_ReturnsErr
ASSERT_NO_FATAL_FAILURE(Initialize());
const size_t pointerCount = 1;
- int32_t pointerIds[pointerCount] = { 0 };
+ PointerProperties pointerProperties[pointerCount];
PointerCoords pointerCoords[pointerCount];
- pointerCoords[0].clear();
+ for (size_t i = 0; i < pointerCount; i++) {
+ pointerProperties[i].clear();
+ pointerCoords[i].clear();
+ }
- status = mPublisher->publishMotionEvent(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- pointerCount, pointerIds, pointerCoords);
+ status = mPublisher->publishMotionEvent(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ pointerCount, pointerProperties, pointerCoords);
ASSERT_EQ(OK, status)
<< "publisher publishMotionEvent should return OK";
- status = mPublisher->publishMotionEvent(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- pointerCount, pointerIds, pointerCoords);
+ status = mPublisher->publishMotionEvent(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ pointerCount, pointerProperties, pointerCoords);
ASSERT_EQ(INVALID_OPERATION, status)
<< "publisher publishMotionEvent should return INVALID_OPERATION because ";
"the publisher was not reset";
@@ -373,11 +385,11 @@ TEST_F(InputPublisherAndConsumerTest, PublishMotionEvent_WhenPointerCountLessTha
ASSERT_NO_FATAL_FAILURE(Initialize());
const size_t pointerCount = 0;
- int32_t pointerIds[pointerCount];
+ PointerProperties pointerProperties[pointerCount];
PointerCoords pointerCoords[pointerCount];
- status = mPublisher->publishMotionEvent(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- pointerCount, pointerIds, pointerCoords);
+ status = mPublisher->publishMotionEvent(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ pointerCount, pointerProperties, pointerCoords);
ASSERT_EQ(BAD_VALUE, status)
<< "publisher publishMotionEvent should return BAD_VALUE";
}
@@ -387,11 +399,15 @@ TEST_F(InputPublisherAndConsumerTest, PublishMotionEvent_WhenPointerCountGreater
ASSERT_NO_FATAL_FAILURE(Initialize());
const size_t pointerCount = MAX_POINTERS + 1;
- int32_t pointerIds[pointerCount];
+ PointerProperties pointerProperties[pointerCount];
PointerCoords pointerCoords[pointerCount];
+ for (size_t i = 0; i < pointerCount; i++) {
+ pointerProperties[i].clear();
+ pointerCoords[i].clear();
+ }
- status = mPublisher->publishMotionEvent(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- pointerCount, pointerIds, pointerCoords);
+ status = mPublisher->publishMotionEvent(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ pointerCount, pointerProperties, pointerCoords);
ASSERT_EQ(BAD_VALUE, status)
<< "publisher publishMotionEvent should return BAD_VALUE";
}
@@ -432,11 +448,15 @@ TEST_F(InputPublisherAndConsumerTest, AppendMotionSample_WhenPublishedMotionEven
ASSERT_NO_FATAL_FAILURE(Initialize());
const size_t pointerCount = MAX_POINTERS;
- int32_t pointerIds[pointerCount];
+ PointerProperties pointerProperties[pointerCount];
PointerCoords pointerCoords[pointerCount];
+ for (size_t i = 0; i < pointerCount; i++) {
+ pointerProperties[i].clear();
+ pointerCoords[i].clear();
+ }
status = mPublisher->publishMotionEvent(0, 0, AMOTION_EVENT_ACTION_DOWN,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, pointerCount, pointerIds, pointerCoords);
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, pointerCount, pointerProperties, pointerCoords);
ASSERT_EQ(OK, status);
status = mPublisher->appendMotionSample(0, pointerCoords);
@@ -449,11 +469,15 @@ TEST_F(InputPublisherAndConsumerTest, AppendMotionSample_WhenAlreadyConsumed_Ret
ASSERT_NO_FATAL_FAILURE(Initialize());
const size_t pointerCount = MAX_POINTERS;
- int32_t pointerIds[pointerCount];
+ PointerProperties pointerProperties[pointerCount];
PointerCoords pointerCoords[pointerCount];
+ for (size_t i = 0; i < pointerCount; i++) {
+ pointerProperties[i].clear();
+ pointerCoords[i].clear();
+ }
status = mPublisher->publishMotionEvent(0, 0, AMOTION_EVENT_ACTION_MOVE,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, pointerCount, pointerIds, pointerCoords);
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, pointerCount, pointerProperties, pointerCoords);
ASSERT_EQ(OK, status);
status = mPublisher->sendDispatchSignal();
@@ -476,11 +500,15 @@ TEST_F(InputPublisherAndConsumerTest, AppendMotionSample_WhenBufferFull_ReturnsE
ASSERT_NO_FATAL_FAILURE(Initialize());
const size_t pointerCount = MAX_POINTERS;
- int32_t pointerIds[pointerCount];
+ PointerProperties pointerProperties[pointerCount];
PointerCoords pointerCoords[pointerCount];
+ for (size_t i = 0; i < pointerCount; i++) {
+ pointerProperties[i].clear();
+ pointerCoords[i].clear();
+ }
status = mPublisher->publishMotionEvent(0, 0, AMOTION_EVENT_ACTION_MOVE,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, pointerCount, pointerIds, pointerCoords);
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, pointerCount, pointerProperties, pointerCoords);
ASSERT_EQ(OK, status);
for (int count = 1;; count++) {
diff --git a/native/android/input.cpp b/native/android/input.cpp
index ed26667..91671c3 100644
--- a/native/android/input.cpp
+++ b/native/android/input.cpp
@@ -92,6 +92,10 @@ int32_t AMotionEvent_getMetaState(const AInputEvent* motion_event) {
return static_cast<const MotionEvent*>(motion_event)->getMetaState();
}
+int32_t AMotionEvent_getButtonState(const AInputEvent* motion_event) {
+ return static_cast<const MotionEvent*>(motion_event)->getButtonState();
+}
+
int32_t AMotionEvent_getEdgeFlags(const AInputEvent* motion_event) {
return reinterpret_cast<const MotionEvent*>(motion_event)->getEdgeFlags();
}
@@ -128,6 +132,10 @@ int32_t AMotionEvent_getPointerId(const AInputEvent* motion_event, size_t pointe
return static_cast<const MotionEvent*>(motion_event)->getPointerId(pointer_index);
}
+int32_t AMotionEvent_getToolType(const AInputEvent* motion_event, size_t pointer_index) {
+ return static_cast<const MotionEvent*>(motion_event)->getToolType(pointer_index);
+}
+
float AMotionEvent_getRawX(const AInputEvent* motion_event, size_t pointer_index) {
return static_cast<const MotionEvent*>(motion_event)->getRawX(pointer_index);
}
diff --git a/native/include/android/input.h b/native/include/android/input.h
index f1738c6..26cac50 100644
--- a/native/include/android/input.h
+++ b/native/include/android/input.h
@@ -372,6 +372,7 @@ enum {
AMOTION_EVENT_AXIS_WHEEL = 21,
AMOTION_EVENT_AXIS_GAS = 22,
AMOTION_EVENT_AXIS_BRAKE = 23,
+ AMOTION_EVENT_AXIS_DISTANCE = 24,
AMOTION_EVENT_AXIS_GENERIC_1 = 32,
AMOTION_EVENT_AXIS_GENERIC_2 = 33,
AMOTION_EVENT_AXIS_GENERIC_3 = 34,
@@ -394,6 +395,32 @@ enum {
};
/*
+ * Constants that identify buttons that are associated with motion events.
+ * Refer to the documentation on the MotionEvent class for descriptions of each button.
+ */
+enum {
+ AMOTION_EVENT_BUTTON_PRIMARY = 1 << 0,
+ AMOTION_EVENT_BUTTON_SECONDARY = 1 << 1,
+ AMOTION_EVENT_BUTTON_TERTIARY = 1 << 2,
+ AMOTION_EVENT_BUTTON_BACK = 1 << 3,
+ AMOTION_EVENT_BUTTON_FORWARD = 1 << 4,
+ AMOTION_EVENT_BUTTON_ERASER = 1 << 5,
+};
+
+/*
+ * Constants that identify tool types.
+ * Refer to the documentation on the MotionEvent class for descriptions of each tool type.
+ */
+enum {
+ AMOTION_EVENT_TOOL_TYPE_UNKNOWN = 0,
+ AMOTION_EVENT_TOOL_TYPE_FINGER = 1,
+ AMOTION_EVENT_TOOL_TYPE_STYLUS = 2,
+ AMOTION_EVENT_TOOL_TYPE_MOUSE = 3,
+ AMOTION_EVENT_TOOL_TYPE_INDIRECT_FINGER = 4,
+ AMOTION_EVENT_TOOL_TYPE_INDIRECT_STYLUS = 5,
+};
+
+/*
* Input sources.
*
* Refer to the documentation on android.view.InputDevice for more details about input sources
@@ -417,6 +444,7 @@ enum {
AINPUT_SOURCE_GAMEPAD = 0x00000400 | AINPUT_SOURCE_CLASS_BUTTON,
AINPUT_SOURCE_TOUCHSCREEN = 0x00001000 | AINPUT_SOURCE_CLASS_POINTER,
AINPUT_SOURCE_MOUSE = 0x00002000 | AINPUT_SOURCE_CLASS_POINTER,
+ AINPUT_SOURCE_STYLUS = 0x00004000 | AINPUT_SOURCE_CLASS_POINTER,
AINPUT_SOURCE_TRACKBALL = 0x00010000 | AINPUT_SOURCE_CLASS_NAVIGATION,
AINPUT_SOURCE_TOUCHPAD = 0x00100000 | AINPUT_SOURCE_CLASS_POSITION,
AINPUT_SOURCE_JOYSTICK = 0x01000000 | AINPUT_SOURCE_CLASS_JOYSTICK,
@@ -532,6 +560,9 @@ int32_t AMotionEvent_getFlags(const AInputEvent* motion_event);
* event was generated. */
int32_t AMotionEvent_getMetaState(const AInputEvent* motion_event);
+/* Get the button state of all buttons that are pressed. */
+int32_t AMotionEvent_getButtonState(const AInputEvent* motion_event);
+
/* Get a bitfield indicating which edges, if any, were touched by this motion event.
* For touch events, clients can use this to determine if the user's finger was
* touching the edge of the display. */
@@ -572,11 +603,16 @@ float AMotionEvent_getYPrecision(const AInputEvent* motion_event);
size_t AMotionEvent_getPointerCount(const AInputEvent* motion_event);
/* Get the pointer identifier associated with a particular pointer
- * data index is this event. The identifier tells you the actual pointer
+ * data index in 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. */
int32_t AMotionEvent_getPointerId(const AInputEvent* motion_event, size_t pointer_index);
+/* Get the tool type of a pointer for the given pointer index.
+ * The tool type indicates the type of tool used to make contact such as a
+ * finger or stylus, if known. */
+int32_t AMotionEvent_getToolType(const AInputEvent* motion_event, size_t pointer_index);
+
/* Get the original raw X coordinate of this event.
* For touch events on the screen, this is the original location of the event
* on the screen, before it had been adjusted for the containing window
diff --git a/services/input/InputDispatcher.cpp b/services/input/InputDispatcher.cpp
index 5bca7ee..8c535d6 100644
--- a/services/input/InputDispatcher.cpp
+++ b/services/input/InputDispatcher.cpp
@@ -150,7 +150,7 @@ static bool isValidMotionAction(int32_t action, size_t pointerCount) {
}
static bool validateMotionEvent(int32_t action, size_t pointerCount,
- const int32_t* pointerIds) {
+ const PointerProperties* pointerProperties) {
if (! isValidMotionAction(action, pointerCount)) {
LOGE("Motion event has invalid action code 0x%x", action);
return false;
@@ -162,7 +162,7 @@ static bool validateMotionEvent(int32_t action, size_t pointerCount,
}
BitSet32 pointerIdBits;
for (size_t i = 0; i < pointerCount; i++) {
- int32_t id = pointerIds[i];
+ int32_t id = pointerProperties[i].id;
if (id < 0 || id > MAX_POINTER_ID) {
LOGE("Motion event has invalid pointer id %d; value must be between 0 and %d",
id, MAX_POINTER_ID);
@@ -899,9 +899,10 @@ bool InputDispatcher::dispatchMotionLocked(
MotionSample* nextSample = splitBatchAfterSample->next;
MotionEntry* nextEntry = mAllocator.obtainMotionEntry(nextSample->eventTime,
entry->deviceId, entry->source, entry->policyFlags,
- entry->action, entry->flags, entry->metaState, entry->edgeFlags,
+ entry->action, entry->flags,
+ entry->metaState, entry->buttonState, entry->edgeFlags,
entry->xPrecision, entry->yPrecision, entry->downTime,
- entry->pointerCount, entry->pointerIds, nextSample->pointerCoords);
+ entry->pointerCount, entry->pointerProperties, nextSample->pointerCoords);
if (nextSample != entry->lastSample) {
nextEntry->firstSample.next = nextSample->next;
nextEntry->lastSample = entry->lastSample;
@@ -941,11 +942,13 @@ void InputDispatcher::logOutboundMotionDetailsLocked(const char* prefix, const M
#if DEBUG_OUTBOUND_EVENT_DETAILS
LOGD("%seventTime=%lld, deviceId=%d, source=0x%x, policyFlags=0x%x, "
"action=0x%x, flags=0x%x, "
- "metaState=0x%x, edgeFlags=0x%x, xPrecision=%f, yPrecision=%f, downTime=%lld",
+ "metaState=0x%x, buttonState=0x%x, "
+ "edgeFlags=0x%x, xPrecision=%f, yPrecision=%f, downTime=%lld",
prefix,
entry->eventTime, entry->deviceId, entry->source, entry->policyFlags,
entry->action, entry->flags,
- entry->metaState, entry->edgeFlags, entry->xPrecision, entry->yPrecision,
+ entry->metaState, entry->buttonState,
+ entry->edgeFlags, entry->xPrecision, entry->yPrecision,
entry->downTime);
// Print the most recent sample that we have available, this may change due to batching.
@@ -955,10 +958,12 @@ void InputDispatcher::logOutboundMotionDetailsLocked(const char* prefix, const M
sampleCount += 1;
}
for (uint32_t i = 0; i < entry->pointerCount; i++) {
- LOGD(" Pointer %d: id=%d, x=%f, y=%f, pressure=%f, size=%f, "
+ LOGD(" Pointer %d: id=%d, toolType=%d, "
+ "x=%f, y=%f, pressure=%f, size=%f, "
"touchMajor=%f, touchMinor=%f, toolMajor=%f, toolMinor=%f, "
"orientation=%f",
- i, entry->pointerIds[i],
+ i, entry->pointerProperties[i].id,
+ entry->pointerProperties[i].toolType,
sample->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_X),
sample->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_Y),
sample->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_PRESSURE),
@@ -1397,7 +1402,7 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime,
// Update the temporary touch state.
BitSet32 pointerIds;
if (isSplit) {
- uint32_t pointerId = entry->pointerIds[pointerIndex];
+ uint32_t pointerId = entry->pointerProperties[pointerIndex].id;
pointerIds.markBit(pointerId);
}
mTempTouchState.addOrUpdateWindow(newTouchedWindow, targetFlags, pointerIds);
@@ -1556,7 +1561,7 @@ Failed:
// One pointer went up.
if (isSplit) {
int32_t pointerIndex = getMotionEventActionPointerIndex(action);
- uint32_t pointerId = entry->pointerIds[pointerIndex];
+ uint32_t pointerId = entry->pointerProperties[pointerIndex].id;
for (size_t i = 0; i < mTempTouchState.windows.size(); ) {
TouchedWindow& touchedWindow = mTempTouchState.windows.editItemAt(i);
@@ -2010,10 +2015,13 @@ void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime,
// Publish the motion event and the first motion sample.
status = connection->inputPublisher.publishMotionEvent(motionEntry->deviceId,
- motionEntry->source, action, flags, motionEntry->edgeFlags, motionEntry->metaState,
- xOffset, yOffset, motionEntry->xPrecision, motionEntry->yPrecision,
+ motionEntry->source, action, flags, motionEntry->edgeFlags,
+ motionEntry->metaState, motionEntry->buttonState,
+ xOffset, yOffset,
+ motionEntry->xPrecision, motionEntry->yPrecision,
motionEntry->downTime, firstMotionSample->eventTime,
- motionEntry->pointerCount, motionEntry->pointerIds, usingCoords);
+ motionEntry->pointerCount, motionEntry->pointerProperties,
+ usingCoords);
if (status) {
LOGE("channel '%s' ~ Could not publish motion event, "
@@ -2027,7 +2035,7 @@ void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime,
// Append additional motion samples.
MotionSample* nextMotionSample = firstMotionSample->next;
for (; nextMotionSample != NULL; nextMotionSample = nextMotionSample->next) {
- if ((motionEntry->source & AINPUT_SOURCE_CLASS_POINTER) != 0 && scaleFactor != 1.0f) {
+ if (usingCoords == scaledCoords) {
for (size_t i = 0; i < motionEntry->pointerCount; i++) {
scaledCoords[i] = nextMotionSample->pointerCoords[i];
scaledCoords[i].scale(scaleFactor);
@@ -2305,7 +2313,7 @@ InputDispatcher::splitMotionEvent(const MotionEntry* originalMotionEntry, BitSet
LOG_ASSERT(pointerIds.value != 0);
uint32_t splitPointerIndexMap[MAX_POINTERS];
- int32_t splitPointerIds[MAX_POINTERS];
+ PointerProperties splitPointerProperties[MAX_POINTERS];
PointerCoords splitPointerCoords[MAX_POINTERS];
uint32_t originalPointerCount = originalMotionEntry->pointerCount;
@@ -2313,10 +2321,12 @@ InputDispatcher::splitMotionEvent(const MotionEntry* originalMotionEntry, BitSet
for (uint32_t originalPointerIndex = 0; originalPointerIndex < originalPointerCount;
originalPointerIndex++) {
- int32_t pointerId = uint32_t(originalMotionEntry->pointerIds[originalPointerIndex]);
+ const PointerProperties& pointerProperties =
+ originalMotionEntry->pointerProperties[originalPointerIndex];
+ uint32_t pointerId = uint32_t(pointerProperties.id);
if (pointerIds.hasBit(pointerId)) {
splitPointerIndexMap[splitPointerCount] = originalPointerIndex;
- splitPointerIds[splitPointerCount] = pointerId;
+ splitPointerProperties[splitPointerCount].copyFrom(pointerProperties);
splitPointerCoords[splitPointerCount].copyFrom(
originalMotionEntry->firstSample.pointerCoords[originalPointerIndex]);
splitPointerCount += 1;
@@ -2341,7 +2351,9 @@ InputDispatcher::splitMotionEvent(const MotionEntry* originalMotionEntry, BitSet
if (maskedAction == AMOTION_EVENT_ACTION_POINTER_DOWN
|| maskedAction == AMOTION_EVENT_ACTION_POINTER_UP) {
int32_t originalPointerIndex = getMotionEventActionPointerIndex(action);
- int32_t pointerId = originalMotionEntry->pointerIds[originalPointerIndex];
+ const PointerProperties& pointerProperties =
+ originalMotionEntry->pointerProperties[originalPointerIndex];
+ uint32_t pointerId = uint32_t(pointerProperties.id);
if (pointerIds.hasBit(pointerId)) {
if (pointerIds.count() == 1) {
// The first/last pointer went down/up.
@@ -2350,7 +2362,7 @@ InputDispatcher::splitMotionEvent(const MotionEntry* originalMotionEntry, BitSet
} else {
// A secondary pointer went down/up.
uint32_t splitPointerIndex = 0;
- while (pointerId != splitPointerIds[splitPointerIndex]) {
+ while (pointerId != uint32_t(splitPointerProperties[splitPointerIndex].id)) {
splitPointerIndex += 1;
}
action = maskedAction | (splitPointerIndex
@@ -2370,11 +2382,12 @@ InputDispatcher::splitMotionEvent(const MotionEntry* originalMotionEntry, BitSet
action,
originalMotionEntry->flags,
originalMotionEntry->metaState,
+ originalMotionEntry->buttonState,
originalMotionEntry->edgeFlags,
originalMotionEntry->xPrecision,
originalMotionEntry->yPrecision,
originalMotionEntry->downTime,
- splitPointerCount, splitPointerIds, splitPointerCoords);
+ splitPointerCount, splitPointerProperties, splitPointerCoords);
for (MotionSample* originalMotionSample = originalMotionEntry->firstSample.next;
originalMotionSample != NULL; originalMotionSample = originalMotionSample->next) {
@@ -2490,20 +2503,25 @@ void InputDispatcher::notifyKey(nsecs_t eventTime, int32_t deviceId, uint32_t so
}
void InputDispatcher::notifyMotion(nsecs_t eventTime, int32_t deviceId, uint32_t source,
- uint32_t policyFlags, int32_t action, int32_t flags, int32_t metaState, int32_t edgeFlags,
- uint32_t pointerCount, const int32_t* pointerIds, const PointerCoords* pointerCoords,
+ uint32_t policyFlags, int32_t action, int32_t flags,
+ int32_t metaState, int32_t buttonState, int32_t edgeFlags,
+ uint32_t pointerCount, const PointerProperties* pointerProperties,
+ const PointerCoords* pointerCoords,
float xPrecision, float yPrecision, nsecs_t downTime) {
#if DEBUG_INBOUND_EVENT_DETAILS
LOGD("notifyMotion - eventTime=%lld, deviceId=%d, source=0x%x, policyFlags=0x%x, "
- "action=0x%x, flags=0x%x, metaState=0x%x, edgeFlags=0x%x, "
+ "action=0x%x, flags=0x%x, metaState=0x%x, buttonState=0x%x, edgeFlags=0x%x, "
"xPrecision=%f, yPrecision=%f, downTime=%lld",
- eventTime, deviceId, source, policyFlags, action, flags, metaState, edgeFlags,
+ eventTime, deviceId, source, policyFlags, action, flags,
+ metaState, buttonState, edgeFlags,
xPrecision, yPrecision, downTime);
for (uint32_t i = 0; i < pointerCount; i++) {
- LOGD(" Pointer %d: id=%d, x=%f, y=%f, pressure=%f, size=%f, "
+ LOGD(" Pointer %d: id=%d, toolType=%d, "
+ "x=%f, y=%f, pressure=%f, size=%f, "
"touchMajor=%f, touchMinor=%f, toolMajor=%f, toolMinor=%f, "
"orientation=%f",
- i, pointerIds[i],
+ i, pointerProperties[i].id,
+ pointerProperties[i].toolType,
pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_X),
pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_Y),
pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_PRESSURE),
@@ -2515,7 +2533,7 @@ void InputDispatcher::notifyMotion(nsecs_t eventTime, int32_t deviceId, uint32_t
pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION));
}
#endif
- if (! validateMotionEvent(action, pointerCount, pointerIds)) {
+ if (! validateMotionEvent(action, pointerCount, pointerProperties)) {
return;
}
@@ -2530,9 +2548,10 @@ void InputDispatcher::notifyMotion(nsecs_t eventTime, int32_t deviceId, uint32_t
mLock.unlock();
MotionEvent event;
- event.initialize(deviceId, source, action, flags, edgeFlags, metaState, 0, 0,
+ event.initialize(deviceId, source, action, flags, edgeFlags, metaState,
+ buttonState, 0, 0,
xPrecision, yPrecision, downTime, eventTime,
- pointerCount, pointerIds, pointerCoords);
+ pointerCount, pointerProperties, pointerCoords);
policyFlags |= POLICY_FLAG_FILTERED;
if (!mPolicy->filterInputEvent(&event, policyFlags)) {
@@ -2564,7 +2583,7 @@ void InputDispatcher::notifyMotion(nsecs_t eventTime, int32_t deviceId, uint32_t
continue;
}
- if (!motionEntry->canAppendSamples(action, pointerCount, pointerIds)) {
+ if (!motionEntry->canAppendSamples(action, pointerCount, pointerProperties)) {
// Last motion event in the queue for this device and source is
// not compatible for appending new samples. Stop here.
goto NoBatchingOrStreaming;
@@ -2587,7 +2606,7 @@ void InputDispatcher::notifyMotion(nsecs_t eventTime, int32_t deviceId, uint32_t
&& mPendingEvent->type == EventEntry::TYPE_MOTION) {
MotionEntry* motionEntry = static_cast<MotionEntry*>(mPendingEvent);
if (motionEntry->deviceId == deviceId && motionEntry->source == source) {
- if (!motionEntry->canAppendSamples(action, pointerCount, pointerIds)) {
+ if (!motionEntry->canAppendSamples(action, pointerCount, pointerProperties)) {
// Pending motion event is for this device and source but it is
// not compatible for appending new samples. Stop here.
goto NoBatchingOrStreaming;
@@ -2696,9 +2715,9 @@ NoBatchingOrStreaming:;
// Just enqueue a new motion event.
MotionEntry* newEntry = mAllocator.obtainMotionEntry(eventTime,
- deviceId, source, policyFlags, action, flags, metaState, edgeFlags,
+ deviceId, source, policyFlags, action, flags, metaState, buttonState, edgeFlags,
xPrecision, yPrecision, downTime,
- pointerCount, pointerIds, pointerCoords);
+ pointerCount, pointerProperties, pointerCoords);
needWake = enqueueInboundEventLocked(newEntry);
mLock.unlock();
@@ -2801,8 +2820,8 @@ int32_t InputDispatcher::injectInputEvent(const InputEvent* event,
const MotionEvent* motionEvent = static_cast<const MotionEvent*>(event);
int32_t action = motionEvent->getAction();
size_t pointerCount = motionEvent->getPointerCount();
- const int32_t* pointerIds = motionEvent->getPointerIds();
- if (! validateMotionEvent(action, pointerCount, pointerIds)) {
+ const PointerProperties* pointerProperties = motionEvent->getPointerProperties();
+ if (! validateMotionEvent(action, pointerCount, pointerProperties)) {
return INPUT_EVENT_INJECTION_FAILED;
}
@@ -2817,10 +2836,11 @@ int32_t InputDispatcher::injectInputEvent(const InputEvent* event,
MotionEntry* motionEntry = mAllocator.obtainMotionEntry(*sampleEventTimes,
motionEvent->getDeviceId(), motionEvent->getSource(), policyFlags,
action, motionEvent->getFlags(),
- motionEvent->getMetaState(), motionEvent->getEdgeFlags(),
+ motionEvent->getMetaState(), motionEvent->getButtonState(),
+ motionEvent->getEdgeFlags(),
motionEvent->getXPrecision(), motionEvent->getYPrecision(),
motionEvent->getDownTime(), uint32_t(pointerCount),
- pointerIds, samplePointerCoords);
+ pointerProperties, samplePointerCoords);
for (size_t i = motionEvent->getHistorySize(); i > 0; i--) {
sampleEventTimes += 1;
samplePointerCoords += pointerCount;
@@ -3553,167 +3573,186 @@ void InputDispatcher::doDispatchCycleFinishedLockedInterruptible(
sp<Connection> connection = commandEntry->connection;
bool handled = commandEntry->handled;
+ bool skipNext = false;
if (!connection->outboundQueue.isEmpty()) {
DispatchEntry* dispatchEntry = connection->outboundQueue.headSentinel.next;
- if (dispatchEntry->inProgress
- && dispatchEntry->eventEntry->type == EventEntry::TYPE_KEY) {
- KeyEntry* keyEntry = static_cast<KeyEntry*>(dispatchEntry->eventEntry);
- if (!(keyEntry->flags & AKEY_EVENT_FLAG_FALLBACK)) {
- // Get the fallback key state.
- // Clear it out after dispatching the UP.
- int32_t originalKeyCode = keyEntry->keyCode;
- int32_t fallbackKeyCode = connection->inputState.getFallbackKey(originalKeyCode);
- if (keyEntry->action == AKEY_EVENT_ACTION_UP) {
- connection->inputState.removeFallbackKey(originalKeyCode);
- }
+ if (dispatchEntry->inProgress) {
+ if (dispatchEntry->eventEntry->type == EventEntry::TYPE_KEY) {
+ KeyEntry* keyEntry = static_cast<KeyEntry*>(dispatchEntry->eventEntry);
+ skipNext = afterKeyEventLockedInterruptible(connection,
+ dispatchEntry, keyEntry, handled);
+ } else if (dispatchEntry->eventEntry->type == EventEntry::TYPE_MOTION) {
+ MotionEntry* motionEntry = static_cast<MotionEntry*>(dispatchEntry->eventEntry);
+ skipNext = afterMotionEventLockedInterruptible(connection,
+ dispatchEntry, motionEntry, handled);
+ }
+ }
+ }
- if (handled || !dispatchEntry->hasForegroundTarget()) {
- // If the application handles the original key for which we previously
- // generated a fallback or if the window is not a foreground window,
- // then cancel the associated fallback key, if any.
- if (fallbackKeyCode != -1) {
- if (fallbackKeyCode != AKEYCODE_UNKNOWN) {
- CancelationOptions options(CancelationOptions::CANCEL_FALLBACK_EVENTS,
- "application handled the original non-fallback key "
- "or is no longer a foreground target, "
- "canceling previously dispatched fallback key");
- options.keyCode = fallbackKeyCode;
- synthesizeCancelationEventsForConnectionLocked(connection, options);
- }
- connection->inputState.removeFallbackKey(originalKeyCode);
- }
- } else {
- // If the application did not handle a non-fallback key, first check
- // that we are in a good state to perform unhandled key event processing
- // Then ask the policy what to do with it.
- bool initialDown = keyEntry->action == AKEY_EVENT_ACTION_DOWN
- && keyEntry->repeatCount == 0;
- if (fallbackKeyCode == -1 && !initialDown) {
+ if (!skipNext) {
+ startNextDispatchCycleLocked(now(), connection);
+ }
+}
+
+bool InputDispatcher::afterKeyEventLockedInterruptible(const sp<Connection>& connection,
+ DispatchEntry* dispatchEntry, KeyEntry* keyEntry, bool handled) {
+ if (!(keyEntry->flags & AKEY_EVENT_FLAG_FALLBACK)) {
+ // Get the fallback key state.
+ // Clear it out after dispatching the UP.
+ int32_t originalKeyCode = keyEntry->keyCode;
+ int32_t fallbackKeyCode = connection->inputState.getFallbackKey(originalKeyCode);
+ if (keyEntry->action == AKEY_EVENT_ACTION_UP) {
+ connection->inputState.removeFallbackKey(originalKeyCode);
+ }
+
+ if (handled || !dispatchEntry->hasForegroundTarget()) {
+ // If the application handles the original key for which we previously
+ // generated a fallback or if the window is not a foreground window,
+ // then cancel the associated fallback key, if any.
+ if (fallbackKeyCode != -1) {
+ if (fallbackKeyCode != AKEYCODE_UNKNOWN) {
+ CancelationOptions options(CancelationOptions::CANCEL_FALLBACK_EVENTS,
+ "application handled the original non-fallback key "
+ "or is no longer a foreground target, "
+ "canceling previously dispatched fallback key");
+ options.keyCode = fallbackKeyCode;
+ synthesizeCancelationEventsForConnectionLocked(connection, options);
+ }
+ connection->inputState.removeFallbackKey(originalKeyCode);
+ }
+ } else {
+ // If the application did not handle a non-fallback key, first check
+ // that we are in a good state to perform unhandled key event processing
+ // Then ask the policy what to do with it.
+ bool initialDown = keyEntry->action == AKEY_EVENT_ACTION_DOWN
+ && keyEntry->repeatCount == 0;
+ if (fallbackKeyCode == -1 && !initialDown) {
#if DEBUG_OUTBOUND_EVENT_DETAILS
- LOGD("Unhandled key event: Skipping unhandled key event processing "
- "since this is not an initial down. "
- "keyCode=%d, action=%d, repeatCount=%d",
- originalKeyCode, keyEntry->action, keyEntry->repeatCount);
+ LOGD("Unhandled key event: Skipping unhandled key event processing "
+ "since this is not an initial down. "
+ "keyCode=%d, action=%d, repeatCount=%d",
+ originalKeyCode, keyEntry->action, keyEntry->repeatCount);
#endif
- goto SkipFallback;
- }
+ return false;
+ }
- // Dispatch the unhandled key to the policy.
+ // Dispatch the unhandled key to the policy.
#if DEBUG_OUTBOUND_EVENT_DETAILS
- LOGD("Unhandled key event: Asking policy to perform fallback action. "
- "keyCode=%d, action=%d, repeatCount=%d",
- keyEntry->keyCode, keyEntry->action, keyEntry->repeatCount);
+ LOGD("Unhandled key event: Asking policy to perform fallback action. "
+ "keyCode=%d, action=%d, repeatCount=%d",
+ keyEntry->keyCode, keyEntry->action, keyEntry->repeatCount);
#endif
- KeyEvent event;
- initializeKeyEvent(&event, keyEntry);
+ KeyEvent event;
+ initializeKeyEvent(&event, keyEntry);
- mLock.unlock();
+ mLock.unlock();
- bool fallback = mPolicy->dispatchUnhandledKey(connection->inputWindowHandle,
- &event, keyEntry->policyFlags, &event);
+ bool fallback = mPolicy->dispatchUnhandledKey(connection->inputWindowHandle,
+ &event, keyEntry->policyFlags, &event);
- mLock.lock();
+ mLock.lock();
- if (connection->status != Connection::STATUS_NORMAL) {
- connection->inputState.removeFallbackKey(originalKeyCode);
- return;
- }
+ if (connection->status != Connection::STATUS_NORMAL) {
+ connection->inputState.removeFallbackKey(originalKeyCode);
+ return true; // skip next cycle
+ }
- LOG_ASSERT(connection->outboundQueue.headSentinel.next == dispatchEntry);
+ LOG_ASSERT(connection->outboundQueue.headSentinel.next == dispatchEntry);
- // Latch the fallback keycode for this key on an initial down.
- // The fallback keycode cannot change at any other point in the lifecycle.
- if (initialDown) {
- if (fallback) {
- fallbackKeyCode = event.getKeyCode();
- } else {
- fallbackKeyCode = AKEYCODE_UNKNOWN;
- }
- connection->inputState.setFallbackKey(originalKeyCode, fallbackKeyCode);
- }
+ // Latch the fallback keycode for this key on an initial down.
+ // The fallback keycode cannot change at any other point in the lifecycle.
+ if (initialDown) {
+ if (fallback) {
+ fallbackKeyCode = event.getKeyCode();
+ } else {
+ fallbackKeyCode = AKEYCODE_UNKNOWN;
+ }
+ connection->inputState.setFallbackKey(originalKeyCode, fallbackKeyCode);
+ }
- LOG_ASSERT(fallbackKeyCode != -1);
+ LOG_ASSERT(fallbackKeyCode != -1);
- // Cancel the fallback key if the policy decides not to send it anymore.
- // We will continue to dispatch the key to the policy but we will no
- // longer dispatch a fallback key to the application.
- if (fallbackKeyCode != AKEYCODE_UNKNOWN
- && (!fallback || fallbackKeyCode != event.getKeyCode())) {
+ // Cancel the fallback key if the policy decides not to send it anymore.
+ // We will continue to dispatch the key to the policy but we will no
+ // longer dispatch a fallback key to the application.
+ if (fallbackKeyCode != AKEYCODE_UNKNOWN
+ && (!fallback || fallbackKeyCode != event.getKeyCode())) {
#if DEBUG_OUTBOUND_EVENT_DETAILS
- if (fallback) {
- LOGD("Unhandled key event: Policy requested to send key %d"
- "as a fallback for %d, but on the DOWN it had requested "
- "to send %d instead. Fallback canceled.",
- event.getKeyCode(), originalKeyCode, fallbackKeyCode);
- } else {
- LOGD("Unhandled key event: Policy did not request fallback for %d,"
- "but on the DOWN it had requested to send %d. "
- "Fallback canceled.",
- originalKeyCode, fallbackKeyCode);
- }
+ if (fallback) {
+ LOGD("Unhandled key event: Policy requested to send key %d"
+ "as a fallback for %d, but on the DOWN it had requested "
+ "to send %d instead. Fallback canceled.",
+ event.getKeyCode(), originalKeyCode, fallbackKeyCode);
+ } else {
+ LOGD("Unhandled key event: Policy did not request fallback for %d,"
+ "but on the DOWN it had requested to send %d. "
+ "Fallback canceled.",
+ originalKeyCode, fallbackKeyCode);
+ }
#endif
- CancelationOptions options(CancelationOptions::CANCEL_FALLBACK_EVENTS,
- "canceling fallback, policy no longer desires it");
- options.keyCode = fallbackKeyCode;
- synthesizeCancelationEventsForConnectionLocked(connection, options);
+ CancelationOptions options(CancelationOptions::CANCEL_FALLBACK_EVENTS,
+ "canceling fallback, policy no longer desires it");
+ options.keyCode = fallbackKeyCode;
+ synthesizeCancelationEventsForConnectionLocked(connection, options);
- fallback = false;
- fallbackKeyCode = AKEYCODE_UNKNOWN;
- if (keyEntry->action != AKEY_EVENT_ACTION_UP) {
- connection->inputState.setFallbackKey(originalKeyCode,
- fallbackKeyCode);
- }
- }
+ fallback = false;
+ fallbackKeyCode = AKEYCODE_UNKNOWN;
+ if (keyEntry->action != AKEY_EVENT_ACTION_UP) {
+ connection->inputState.setFallbackKey(originalKeyCode,
+ fallbackKeyCode);
+ }
+ }
#if DEBUG_OUTBOUND_EVENT_DETAILS
- {
- String8 msg;
- const KeyedVector<int32_t, int32_t>& fallbackKeys =
- connection->inputState.getFallbackKeys();
- for (size_t i = 0; i < fallbackKeys.size(); i++) {
- msg.appendFormat(", %d->%d", fallbackKeys.keyAt(i),
- fallbackKeys.valueAt(i));
- }
- LOGD("Unhandled key event: %d currently tracked fallback keys%s.",
- fallbackKeys.size(), msg.string());
- }
+ {
+ String8 msg;
+ const KeyedVector<int32_t, int32_t>& fallbackKeys =
+ connection->inputState.getFallbackKeys();
+ for (size_t i = 0; i < fallbackKeys.size(); i++) {
+ msg.appendFormat(", %d->%d", fallbackKeys.keyAt(i),
+ fallbackKeys.valueAt(i));
+ }
+ LOGD("Unhandled key event: %d currently tracked fallback keys%s.",
+ fallbackKeys.size(), msg.string());
+ }
#endif
- if (fallback) {
- // Restart the dispatch cycle using the fallback key.
- keyEntry->eventTime = event.getEventTime();
- keyEntry->deviceId = event.getDeviceId();
- keyEntry->source = event.getSource();
- keyEntry->flags = event.getFlags() | AKEY_EVENT_FLAG_FALLBACK;
- keyEntry->keyCode = fallbackKeyCode;
- keyEntry->scanCode = event.getScanCode();
- keyEntry->metaState = event.getMetaState();
- keyEntry->repeatCount = event.getRepeatCount();
- keyEntry->downTime = event.getDownTime();
- keyEntry->syntheticRepeat = false;
+ if (fallback) {
+ // Restart the dispatch cycle using the fallback key.
+ keyEntry->eventTime = event.getEventTime();
+ keyEntry->deviceId = event.getDeviceId();
+ keyEntry->source = event.getSource();
+ keyEntry->flags = event.getFlags() | AKEY_EVENT_FLAG_FALLBACK;
+ keyEntry->keyCode = fallbackKeyCode;
+ keyEntry->scanCode = event.getScanCode();
+ keyEntry->metaState = event.getMetaState();
+ keyEntry->repeatCount = event.getRepeatCount();
+ keyEntry->downTime = event.getDownTime();
+ keyEntry->syntheticRepeat = false;
#if DEBUG_OUTBOUND_EVENT_DETAILS
- LOGD("Unhandled key event: Dispatching fallback key. "
- "originalKeyCode=%d, fallbackKeyCode=%d, fallbackMetaState=%08x",
- originalKeyCode, fallbackKeyCode, keyEntry->metaState);
+ LOGD("Unhandled key event: Dispatching fallback key. "
+ "originalKeyCode=%d, fallbackKeyCode=%d, fallbackMetaState=%08x",
+ originalKeyCode, fallbackKeyCode, keyEntry->metaState);
#endif
- dispatchEntry->inProgress = false;
- startDispatchCycleLocked(now(), connection);
- return;
- } else {
+ dispatchEntry->inProgress = false;
+ startDispatchCycleLocked(now(), connection);
+ return true; // already started next cycle
+ } else {
#if DEBUG_OUTBOUND_EVENT_DETAILS
- LOGD("Unhandled key event: No fallback key.");
+ LOGD("Unhandled key event: No fallback key.");
#endif
- }
- }
}
}
}
+ return false;
+}
-SkipFallback:
- startNextDispatchCycleLocked(now(), connection);
+bool InputDispatcher::afterMotionEventLockedInterruptible(const sp<Connection>& connection,
+ DispatchEntry* dispatchEntry, MotionEntry* motionEntry, bool handled) {
+ return false;
}
void InputDispatcher::doPokeUserActivityLockedInterruptible(CommandEntry* commandEntry) {
@@ -3817,9 +3856,10 @@ InputDispatcher::KeyEntry* InputDispatcher::Allocator::obtainKeyEntry(nsecs_t ev
InputDispatcher::MotionEntry* InputDispatcher::Allocator::obtainMotionEntry(nsecs_t eventTime,
int32_t deviceId, uint32_t source, uint32_t policyFlags, int32_t action, int32_t flags,
- int32_t metaState, int32_t edgeFlags, float xPrecision, float yPrecision,
+ int32_t metaState, int32_t buttonState,
+ int32_t edgeFlags, float xPrecision, float yPrecision,
nsecs_t downTime, uint32_t pointerCount,
- const int32_t* pointerIds, const PointerCoords* pointerCoords) {
+ const PointerProperties* pointerProperties, const PointerCoords* pointerCoords) {
MotionEntry* entry = mMotionEntryPool.alloc();
initializeEventEntry(entry, EventEntry::TYPE_MOTION, eventTime, policyFlags);
@@ -3829,6 +3869,7 @@ InputDispatcher::MotionEntry* InputDispatcher::Allocator::obtainMotionEntry(nsec
entry->action = action;
entry->flags = flags;
entry->metaState = metaState;
+ entry->buttonState = buttonState;
entry->edgeFlags = edgeFlags;
entry->xPrecision = xPrecision;
entry->yPrecision = yPrecision;
@@ -3839,7 +3880,7 @@ InputDispatcher::MotionEntry* InputDispatcher::Allocator::obtainMotionEntry(nsec
entry->firstSample.next = NULL;
entry->lastSample = & entry->firstSample;
for (uint32_t i = 0; i < pointerCount; i++) {
- entry->pointerIds[i] = pointerIds[i];
+ entry->pointerProperties[i].copyFrom(pointerProperties[i]);
entry->firstSample.pointerCoords[i].copyFrom(pointerCoords[i]);
}
return entry;
@@ -3977,14 +4018,14 @@ uint32_t InputDispatcher::MotionEntry::countSamples() const {
}
bool InputDispatcher::MotionEntry::canAppendSamples(int32_t action, uint32_t pointerCount,
- const int32_t* pointerIds) const {
+ const PointerProperties* pointerProperties) const {
if (this->action != action
|| this->pointerCount != pointerCount
|| this->isInjected()) {
return false;
}
for (uint32_t i = 0; i < pointerCount; i++) {
- if (this->pointerIds[i] != pointerIds[i]) {
+ if (this->pointerProperties[i] != pointerProperties[i]) {
return false;
}
}
@@ -4114,7 +4155,7 @@ Found:
void InputDispatcher::InputState::MotionMemento::setPointers(const MotionEntry* entry) {
pointerCount = entry->pointerCount;
for (uint32_t i = 0; i < entry->pointerCount; i++) {
- pointerIds[i] = entry->pointerIds[i];
+ pointerProperties[i].copyFrom(entry->pointerProperties[i]);
pointerCoords[i].copyFrom(entry->lastSample->pointerCoords[i]);
}
}
@@ -4143,9 +4184,9 @@ void InputDispatcher::InputState::synthesizeCancelationEvents(nsecs_t currentTim
memento.hovering
? AMOTION_EVENT_ACTION_HOVER_EXIT
: AMOTION_EVENT_ACTION_CANCEL,
- 0, 0, 0,
+ 0, 0, 0, 0,
memento.xPrecision, memento.yPrecision, memento.downTime,
- memento.pointerCount, memento.pointerIds, memento.pointerCoords));
+ memento.pointerCount, memento.pointerProperties, memento.pointerCoords));
mMotionMementos.removeAt(i);
} else {
i += 1;
diff --git a/services/input/InputDispatcher.h b/services/input/InputDispatcher.h
index 96ece32..9ac5b75 100644
--- a/services/input/InputDispatcher.h
+++ b/services/input/InputDispatcher.h
@@ -263,8 +263,9 @@ public:
int32_t scanCode, int32_t metaState, nsecs_t downTime) = 0;
virtual void notifyMotion(nsecs_t eventTime, int32_t deviceId, uint32_t source,
uint32_t policyFlags, int32_t action, int32_t flags,
- int32_t metaState, int32_t edgeFlags,
- uint32_t pointerCount, const int32_t* pointerIds, const PointerCoords* pointerCoords,
+ int32_t metaState, int32_t buttonState, int32_t edgeFlags,
+ uint32_t pointerCount, const PointerProperties* pointerProperties,
+ const PointerCoords* pointerCoords,
float xPrecision, float yPrecision, nsecs_t downTime) = 0;
virtual void notifySwitch(nsecs_t when,
int32_t switchCode, int32_t switchValue, uint32_t policyFlags) = 0;
@@ -358,8 +359,9 @@ public:
int32_t scanCode, int32_t metaState, nsecs_t downTime);
virtual void notifyMotion(nsecs_t eventTime, int32_t deviceId, uint32_t source,
uint32_t policyFlags, int32_t action, int32_t flags,
- int32_t metaState, int32_t edgeFlags,
- uint32_t pointerCount, const int32_t* pointerIds, const PointerCoords* pointerCoords,
+ int32_t metaState, int32_t buttonState, int32_t edgeFlags,
+ uint32_t pointerCount, const PointerProperties* pointerProperties,
+ const PointerCoords* pointerCoords,
float xPrecision, float yPrecision, nsecs_t downTime);
virtual void notifySwitch(nsecs_t when,
int32_t switchCode, int32_t switchValue, uint32_t policyFlags) ;
@@ -454,12 +456,13 @@ private:
int32_t action;
int32_t flags;
int32_t metaState;
+ int32_t buttonState;
int32_t edgeFlags;
float xPrecision;
float yPrecision;
nsecs_t downTime;
uint32_t pointerCount;
- int32_t pointerIds[MAX_POINTERS];
+ PointerProperties pointerProperties[MAX_POINTERS];
// Linked list of motion samples associated with this motion event.
MotionSample firstSample;
@@ -469,7 +472,7 @@ private:
// Checks whether we can append samples, assuming the device id and source are the same.
bool canAppendSamples(int32_t action, uint32_t pointerCount,
- const int32_t* pointerIds) const;
+ const PointerProperties* pointerProperties) const;
};
// Tracks the progress of dispatching a particular event to a particular connection.
@@ -602,10 +605,10 @@ private:
int32_t repeatCount, nsecs_t downTime);
MotionEntry* obtainMotionEntry(nsecs_t eventTime,
int32_t deviceId, uint32_t source, uint32_t policyFlags, int32_t action,
- int32_t flags, int32_t metaState, int32_t edgeFlags,
+ int32_t flags, int32_t metaState, int32_t buttonState, int32_t edgeFlags,
float xPrecision, float yPrecision,
nsecs_t downTime, uint32_t pointerCount,
- const int32_t* pointerIds, const PointerCoords* pointerCoords);
+ const PointerProperties* pointerProperties, const PointerCoords* pointerCoords);
DispatchEntry* obtainDispatchEntry(EventEntry* eventEntry,
int32_t targetFlags, float xOffset, float yOffset, float scaleFactor);
CommandEntry* obtainCommandEntry(Command command);
@@ -721,7 +724,7 @@ private:
float yPrecision;
nsecs_t downTime;
uint32_t pointerCount;
- int32_t pointerIds[MAX_POINTERS];
+ PointerProperties pointerProperties[MAX_POINTERS];
PointerCoords pointerCoords[MAX_POINTERS];
bool hovering;
@@ -1053,6 +1056,10 @@ private:
void doNotifyANRLockedInterruptible(CommandEntry* commandEntry);
void doInterceptKeyBeforeDispatchingLockedInterruptible(CommandEntry* commandEntry);
void doDispatchCycleFinishedLockedInterruptible(CommandEntry* commandEntry);
+ bool afterKeyEventLockedInterruptible(const sp<Connection>& connection,
+ DispatchEntry* dispatchEntry, KeyEntry* keyEntry, bool handled);
+ bool afterMotionEventLockedInterruptible(const sp<Connection>& connection,
+ DispatchEntry* dispatchEntry, MotionEntry* motionEntry, bool handled);
void doPokeUserActivityLockedInterruptible(CommandEntry* commandEntry);
void initializeKeyEvent(KeyEvent* event, const KeyEntry* entry);
diff --git a/services/input/InputReader.cpp b/services/input/InputReader.cpp
index 98b3526..6003207 100644
--- a/services/input/InputReader.cpp
+++ b/services/input/InputReader.cpp
@@ -208,23 +208,32 @@ static uint32_t getButtonStateForScanCode(int32_t scanCode) {
// Currently all buttons are mapped to the primary button.
switch (scanCode) {
case BTN_LEFT:
+ return AMOTION_EVENT_BUTTON_PRIMARY;
case BTN_RIGHT:
+ return AMOTION_EVENT_BUTTON_SECONDARY;
case BTN_MIDDLE:
+ return AMOTION_EVENT_BUTTON_TERTIARY;
case BTN_SIDE:
+ return AMOTION_EVENT_BUTTON_BACK;
case BTN_EXTRA:
+ return AMOTION_EVENT_BUTTON_FORWARD;
case BTN_FORWARD:
+ return AMOTION_EVENT_BUTTON_FORWARD;
case BTN_BACK:
+ return AMOTION_EVENT_BUTTON_BACK;
case BTN_TASK:
- return BUTTON_STATE_PRIMARY;
default:
return 0;
}
}
// Returns true if the pointer should be reported as being down given the specified
-// button states.
-static bool isPointerDown(uint32_t buttonState) {
- return buttonState & BUTTON_STATE_PRIMARY;
+// button states. This determines whether the event is reported as a touch event.
+static bool isPointerDown(int32_t buttonState) {
+ return buttonState &
+ (AMOTION_EVENT_BUTTON_PRIMARY | AMOTION_EVENT_BUTTON_SECONDARY
+ | AMOTION_EVENT_BUTTON_TERTIARY
+ | AMOTION_EVENT_BUTTON_ERASER);
}
static int32_t calculateEdgeFlagsUsingPointerBounds(
@@ -273,6 +282,33 @@ static float calculateCommonVector(float a, float b) {
}
}
+static void synthesizeButtonKey(InputReaderContext* context, int32_t action,
+ nsecs_t when, int32_t deviceId, uint32_t source,
+ uint32_t policyFlags, int32_t lastButtonState, int32_t currentButtonState,
+ int32_t buttonState, int32_t keyCode) {
+ if (
+ (action == AKEY_EVENT_ACTION_DOWN
+ && !(lastButtonState & buttonState)
+ && (currentButtonState & buttonState))
+ || (action == AKEY_EVENT_ACTION_UP
+ && (lastButtonState & buttonState)
+ && !(currentButtonState & buttonState))) {
+ context->getDispatcher()->notifyKey(when, deviceId, source, policyFlags,
+ action, 0, keyCode, 0, context->getGlobalMetaState(), when);
+ }
+}
+
+static void synthesizeButtonKeys(InputReaderContext* context, int32_t action,
+ nsecs_t when, int32_t deviceId, uint32_t source,
+ uint32_t policyFlags, int32_t lastButtonState, int32_t currentButtonState) {
+ synthesizeButtonKey(context, action, when, deviceId, source, policyFlags,
+ lastButtonState, currentButtonState,
+ AMOTION_EVENT_BUTTON_BACK, AKEYCODE_BACK);
+ synthesizeButtonKey(context, action, when, deviceId, source, policyFlags,
+ lastButtonState, currentButtonState,
+ AMOTION_EVENT_BUTTON_FORWARD, AKEYCODE_FORWARD);
+}
+
// --- InputReader ---
@@ -1443,7 +1479,7 @@ void CursorInputMapper::initializeLocked() {
void CursorInputMapper::reset() {
for (;;) {
- uint32_t buttonState;
+ int32_t buttonState;
{ // acquire lock
AutoMutex _l(mLock);
@@ -1469,7 +1505,7 @@ void CursorInputMapper::reset() {
void CursorInputMapper::process(const RawEvent* rawEvent) {
switch (rawEvent->type) {
case EV_KEY: {
- uint32_t buttonState = getButtonStateForScanCode(rawEvent->scanCode);
+ int32_t buttonState = getButtonStateForScanCode(rawEvent->scanCode);
if (buttonState) {
if (rawEvent->value) {
mAccumulator.buttonDown = buttonState;
@@ -1527,12 +1563,16 @@ void CursorInputMapper::sync(nsecs_t when) {
int32_t motionEventAction;
int32_t motionEventEdgeFlags;
+ int32_t lastButtonState, currentButtonState;
+ PointerProperties pointerProperties;
PointerCoords pointerCoords;
nsecs_t downTime;
float vscroll, hscroll;
{ // acquire lock
AutoMutex _l(mLock);
+ lastButtonState = mLocked.buttonState;
+
bool down, downChanged;
bool wasDown = isPointerDown(mLocked.buttonState);
bool buttonsChanged = fields & Accumulator::FIELD_BUTTONS;
@@ -1555,6 +1595,8 @@ void CursorInputMapper::sync(nsecs_t when) {
downChanged = false;
}
+ currentButtonState = mLocked.buttonState;
+
downTime = mLocked.downTime;
float deltaX = fields & Accumulator::FIELD_REL_X ? mAccumulator.relX * mXScale : 0.0f;
float deltaY = fields & Accumulator::FIELD_REL_Y ? mAccumulator.relY * mYScale : 0.0f;
@@ -1598,10 +1640,14 @@ void CursorInputMapper::sync(nsecs_t when) {
}
}
- pointerCoords.clear();
-
motionEventEdgeFlags = AMOTION_EVENT_EDGE_FLAG_NONE;
+ pointerProperties.clear();
+ pointerProperties.id = 0;
+ pointerProperties.toolType = AMOTION_EVENT_TOOL_TYPE_MOUSE;
+
+ pointerCoords.clear();
+
if (mHaveVWheel && (fields & Accumulator::FIELD_REL_WHEEL)) {
vscroll = mAccumulator.relWheel;
} else {
@@ -1656,18 +1702,23 @@ void CursorInputMapper::sync(nsecs_t when) {
policyFlags |= POLICY_FLAG_WAKE_DROPPED;
}
+ // Synthesize key down from buttons if needed.
+ synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_DOWN, when, getDeviceId(), mSource,
+ policyFlags, lastButtonState, currentButtonState);
+
+ // Send motion event.
int32_t metaState = mContext->getGlobalMetaState();
- int32_t pointerId = 0;
getDispatcher()->notifyMotion(when, getDeviceId(), mSource, policyFlags,
- motionEventAction, 0, metaState, motionEventEdgeFlags,
- 1, &pointerId, &pointerCoords, mXPrecision, mYPrecision, downTime);
+ motionEventAction, 0, metaState, currentButtonState, motionEventEdgeFlags,
+ 1, &pointerProperties, &pointerCoords, mXPrecision, mYPrecision, downTime);
// Send hover move after UP to tell the application that the mouse is hovering now.
if (motionEventAction == AMOTION_EVENT_ACTION_UP
&& mPointerController != NULL) {
getDispatcher()->notifyMotion(when, getDeviceId(), mSource, policyFlags,
- AMOTION_EVENT_ACTION_HOVER_MOVE, 0, metaState, AMOTION_EVENT_EDGE_FLAG_NONE,
- 1, &pointerId, &pointerCoords, mXPrecision, mYPrecision, downTime);
+ AMOTION_EVENT_ACTION_HOVER_MOVE, 0,
+ metaState, currentButtonState, AMOTION_EVENT_EDGE_FLAG_NONE,
+ 1, &pointerProperties, &pointerCoords, mXPrecision, mYPrecision, downTime);
}
// Send scroll events.
@@ -1676,10 +1727,15 @@ void CursorInputMapper::sync(nsecs_t when) {
pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_HSCROLL, hscroll);
getDispatcher()->notifyMotion(when, getDeviceId(), mSource, policyFlags,
- AMOTION_EVENT_ACTION_SCROLL, 0, metaState, AMOTION_EVENT_EDGE_FLAG_NONE,
- 1, &pointerId, &pointerCoords, mXPrecision, mYPrecision, downTime);
+ AMOTION_EVENT_ACTION_SCROLL, 0, metaState, currentButtonState,
+ AMOTION_EVENT_EDGE_FLAG_NONE,
+ 1, &pointerProperties, &pointerCoords, mXPrecision, mYPrecision, downTime);
}
+ // Synthesize key up from buttons if needed.
+ synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_UP, when, getDeviceId(), mSource,
+ policyFlags, lastButtonState, currentButtonState);
+
mAccumulator.clear();
}
@@ -2766,6 +2822,11 @@ void TouchInputMapper::syncTouch(nsecs_t when, bool havePointerIds) {
}
}
+ // Synthesize key down from buttons if needed.
+ synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_DOWN, when, getDeviceId(), mTouchSource,
+ policyFlags, mLastTouch.buttonState, mCurrentTouch.buttonState);
+
+ // Send motion events.
TouchResult touchResult;
if (mLastTouch.pointerCount == 0 && mCurrentTouch.pointerCount == 0
&& mLastTouch.buttonState == mCurrentTouch.buttonState) {
@@ -2783,6 +2844,10 @@ void TouchInputMapper::syncTouch(nsecs_t when, bool havePointerIds) {
}
}
+ // Synthesize key up from buttons if needed.
+ synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_UP, when, getDeviceId(), mTouchSource,
+ policyFlags, mLastTouch.buttonState, mCurrentTouch.buttonState);
+
// Copy current touch to last touch in preparation for the next cycle.
// Keep the button state so we can track edge-triggered button state changes.
if (touchResult == DROP_STROKE) {
@@ -2949,14 +3014,17 @@ void TouchInputMapper::dispatchTouches(nsecs_t when, uint32_t policyFlags) {
// Dispatch motions.
BitSet32 currentIdBits = mCurrentTouch.idBits;
BitSet32 lastIdBits = mLastTouch.idBits;
- uint32_t metaState = getContext()->getGlobalMetaState();
+ int32_t metaState = getContext()->getGlobalMetaState();
+ int32_t buttonState = mCurrentTouch.buttonState;
if (currentIdBits == lastIdBits) {
// No pointer id changes so this is a move event.
// The dispatcher takes care of batching moves so we don't have to deal with that here.
dispatchMotion(when, policyFlags, mTouchSource,
- AMOTION_EVENT_ACTION_MOVE, 0, metaState, AMOTION_EVENT_EDGE_FLAG_NONE,
- mCurrentTouchCoords, mCurrentTouch.idToIndex, currentIdBits, -1,
+ AMOTION_EVENT_ACTION_MOVE, 0, metaState, buttonState,
+ AMOTION_EVENT_EDGE_FLAG_NONE,
+ mCurrentTouchProperties, mCurrentTouchCoords,
+ mCurrentTouch.idToIndex, currentIdBits, -1,
xPrecision, yPrecision, mDownTime);
} else {
// There may be pointers going up and pointers going down and pointers moving
@@ -2968,10 +3036,13 @@ void TouchInputMapper::dispatchTouches(nsecs_t when, uint32_t policyFlags) {
// Update last coordinates of pointers that have moved so that we observe the new
// pointer positions at the same time as other pointers that have just gone up.
- bool moveNeeded = updateMovedPointerCoords(
- mCurrentTouchCoords, mCurrentTouch.idToIndex,
- mLastTouchCoords, mLastTouch.idToIndex,
+ bool moveNeeded = updateMovedPointers(
+ mCurrentTouchProperties, mCurrentTouchCoords, mCurrentTouch.idToIndex,
+ mLastTouchProperties, mLastTouchCoords, mLastTouch.idToIndex,
moveIdBits);
+ if (buttonState != mLastTouch.buttonState) {
+ moveNeeded = true;
+ }
// Dispatch pointer up events.
while (!upIdBits.isEmpty()) {
@@ -2979,8 +3050,9 @@ void TouchInputMapper::dispatchTouches(nsecs_t when, uint32_t policyFlags) {
upIdBits.clearBit(upId);
dispatchMotion(when, policyFlags, mTouchSource,
- AMOTION_EVENT_ACTION_POINTER_UP, 0, metaState, 0,
- mLastTouchCoords, mLastTouch.idToIndex, dispatchedIdBits, upId,
+ AMOTION_EVENT_ACTION_POINTER_UP, 0, metaState, buttonState, 0,
+ mLastTouchProperties, mLastTouchCoords,
+ mLastTouch.idToIndex, dispatchedIdBits, upId,
xPrecision, yPrecision, mDownTime);
dispatchedIdBits.clearBit(upId);
}
@@ -2991,8 +3063,9 @@ void TouchInputMapper::dispatchTouches(nsecs_t when, uint32_t policyFlags) {
if (moveNeeded) {
LOG_ASSERT(moveIdBits.value == dispatchedIdBits.value);
dispatchMotion(when, policyFlags, mTouchSource,
- AMOTION_EVENT_ACTION_MOVE, 0, metaState, 0,
- mCurrentTouchCoords, mCurrentTouch.idToIndex, dispatchedIdBits, -1,
+ AMOTION_EVENT_ACTION_MOVE, 0, metaState, buttonState, 0,
+ mCurrentTouchProperties, mCurrentTouchCoords,
+ mCurrentTouch.idToIndex, dispatchedIdBits, -1,
xPrecision, yPrecision, mDownTime);
}
@@ -3011,14 +3084,16 @@ void TouchInputMapper::dispatchTouches(nsecs_t when, uint32_t policyFlags) {
}
dispatchMotion(when, policyFlags, mTouchSource,
- AMOTION_EVENT_ACTION_POINTER_DOWN, 0, metaState, edgeFlags,
- mCurrentTouchCoords, mCurrentTouch.idToIndex, dispatchedIdBits, downId,
+ AMOTION_EVENT_ACTION_POINTER_DOWN, 0, metaState, buttonState, edgeFlags,
+ mCurrentTouchProperties, mCurrentTouchCoords,
+ mCurrentTouch.idToIndex, dispatchedIdBits, downId,
xPrecision, yPrecision, mDownTime);
}
}
// Update state for next time.
for (uint32_t i = 0; i < currentPointerCount; i++) {
+ mLastTouchProperties[i].copyFrom(mCurrentTouchProperties[i]);
mLastTouchCoords[i].copyFrom(mCurrentTouchCoords[i]);
}
}
@@ -3214,6 +3289,12 @@ void TouchInputMapper::prepareTouches(int32_t* outEdgeFlags,
out.setAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR, toolMajor);
out.setAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR, toolMinor);
out.setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, orientation);
+
+ // Write output properties.
+ PointerProperties& properties = mCurrentTouchProperties[i];
+ properties.clear();
+ properties.id = mCurrentTouch.pointers[i].id;
+ properties.toolType = getTouchToolType(mCurrentTouch.pointers[i].isStylus);
}
// Check edge flags by looking only at the first pointer since the flags are
@@ -3265,7 +3346,8 @@ void TouchInputMapper::dispatchPointerGestures(nsecs_t when, uint32_t policyFlag
}
// Send events!
- uint32_t metaState = getContext()->getGlobalMetaState();
+ int32_t metaState = getContext()->getGlobalMetaState();
+ int32_t buttonState = mCurrentTouch.buttonState;
// Update last coordinates of pointers that have moved so that we observe the new
// pointer positions at the same time as other pointers that have just gone up.
@@ -3281,10 +3363,14 @@ void TouchInputMapper::dispatchPointerGestures(nsecs_t when, uint32_t policyFlag
&& !mPointerGesture.currentGestureIdBits.isEmpty()) {
BitSet32 movedGestureIdBits(mPointerGesture.currentGestureIdBits.value
& mPointerGesture.lastGestureIdBits.value);
- moveNeeded = updateMovedPointerCoords(
+ moveNeeded = updateMovedPointers(mPointerGesture.currentGestureProperties,
mPointerGesture.currentGestureCoords, mPointerGesture.currentGestureIdToIndex,
+ mPointerGesture.lastGestureProperties,
mPointerGesture.lastGestureCoords, mPointerGesture.lastGestureIdToIndex,
movedGestureIdBits);
+ if (buttonState != mLastTouch.buttonState) {
+ moveNeeded = true;
+ }
}
// Send motion events for all pointers that went up or were canceled.
@@ -3292,7 +3378,9 @@ void TouchInputMapper::dispatchPointerGestures(nsecs_t when, uint32_t policyFlag
if (!dispatchedGestureIdBits.isEmpty()) {
if (cancelPreviousGesture) {
dispatchMotion(when, policyFlags, mPointerSource,
- AMOTION_EVENT_ACTION_CANCEL, 0, metaState, AMOTION_EVENT_EDGE_FLAG_NONE,
+ AMOTION_EVENT_ACTION_CANCEL, 0, metaState, buttonState,
+ AMOTION_EVENT_EDGE_FLAG_NONE,
+ mPointerGesture.lastGestureProperties,
mPointerGesture.lastGestureCoords, mPointerGesture.lastGestureIdToIndex,
dispatchedGestureIdBits, -1,
0, 0, mPointerGesture.downTime);
@@ -3312,7 +3400,8 @@ void TouchInputMapper::dispatchPointerGestures(nsecs_t when, uint32_t policyFlag
dispatchMotion(when, policyFlags, mPointerSource,
AMOTION_EVENT_ACTION_POINTER_UP, 0,
- metaState, AMOTION_EVENT_EDGE_FLAG_NONE,
+ metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
+ mPointerGesture.lastGestureProperties,
mPointerGesture.lastGestureCoords, mPointerGesture.lastGestureIdToIndex,
dispatchedGestureIdBits, id,
0, 0, mPointerGesture.downTime);
@@ -3325,7 +3414,8 @@ void TouchInputMapper::dispatchPointerGestures(nsecs_t when, uint32_t policyFlag
// Send motion events for all pointers that moved.
if (moveNeeded) {
dispatchMotion(when, policyFlags, mPointerSource,
- AMOTION_EVENT_ACTION_MOVE, 0, metaState, AMOTION_EVENT_EDGE_FLAG_NONE,
+ AMOTION_EVENT_ACTION_MOVE, 0, metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
+ mPointerGesture.currentGestureProperties,
mPointerGesture.currentGestureCoords, mPointerGesture.currentGestureIdToIndex,
dispatchedGestureIdBits, -1,
0, 0, mPointerGesture.downTime);
@@ -3352,7 +3442,8 @@ void TouchInputMapper::dispatchPointerGestures(nsecs_t when, uint32_t policyFlag
}
dispatchMotion(when, policyFlags, mPointerSource,
- AMOTION_EVENT_ACTION_POINTER_DOWN, 0, metaState, edgeFlags,
+ AMOTION_EVENT_ACTION_POINTER_DOWN, 0, metaState, buttonState, edgeFlags,
+ mPointerGesture.currentGestureProperties,
mPointerGesture.currentGestureCoords, mPointerGesture.currentGestureIdToIndex,
dispatchedGestureIdBits, id,
0, 0, mPointerGesture.downTime);
@@ -3362,7 +3453,9 @@ void TouchInputMapper::dispatchPointerGestures(nsecs_t when, uint32_t policyFlag
// Send motion events for hover.
if (mPointerGesture.currentGestureMode == PointerGesture::HOVER) {
dispatchMotion(when, policyFlags, mPointerSource,
- AMOTION_EVENT_ACTION_HOVER_MOVE, 0, metaState, AMOTION_EVENT_EDGE_FLAG_NONE,
+ AMOTION_EVENT_ACTION_HOVER_MOVE, 0,
+ metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
+ mPointerGesture.currentGestureProperties,
mPointerGesture.currentGestureCoords, mPointerGesture.currentGestureIdToIndex,
mPointerGesture.currentGestureIdBits, -1,
0, 0, mPointerGesture.downTime);
@@ -3378,6 +3471,8 @@ void TouchInputMapper::dispatchPointerGestures(nsecs_t when, uint32_t policyFlag
uint32_t id = idBits.firstMarkedBit();
idBits.clearBit(id);
uint32_t index = mPointerGesture.currentGestureIdToIndex[id];
+ mPointerGesture.lastGestureProperties[index].copyFrom(
+ mPointerGesture.currentGestureProperties[index]);
mPointerGesture.lastGestureCoords[index].copyFrom(
mPointerGesture.currentGestureCoords[index]);
mPointerGesture.lastGestureIdToIndex[id] = index;
@@ -3413,8 +3508,6 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when,
mPointerGesture.currentGestureMode = PointerGesture::NEUTRAL;
mPointerGesture.currentGestureIdBits.clear();
- mPointerController->setButtonState(0);
-
if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS) {
mPointerGesture.spotGesture = PointerControllerInterface::SPOT_GESTURE_NEUTRAL;
mPointerGesture.spotIdBits.clear();
@@ -3509,8 +3602,6 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when,
mPointerGesture.currentGestureMode = PointerGesture::QUIET;
mPointerGesture.currentGestureIdBits.clear();
- mPointerController->setButtonState(0);
-
if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS) {
mPointerGesture.spotGesture = PointerControllerInterface::SPOT_GESTURE_NEUTRAL;
mPointerGesture.spotIdBits.clear();
@@ -3591,13 +3682,15 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when,
mPointerGesture.currentGestureIdBits.clear();
mPointerGesture.currentGestureIdBits.markBit(mPointerGesture.activeGestureId);
mPointerGesture.currentGestureIdToIndex[mPointerGesture.activeGestureId] = 0;
+ mPointerGesture.currentGestureProperties[0].clear();
+ mPointerGesture.currentGestureProperties[0].id = mPointerGesture.activeGestureId;
+ mPointerGesture.currentGestureProperties[0].toolType =
+ AMOTION_EVENT_TOOL_TYPE_INDIRECT_FINGER;
mPointerGesture.currentGestureCoords[0].clear();
mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, x);
mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, y);
mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 1.0f);
- mPointerController->setButtonState(BUTTON_STATE_PRIMARY);
-
if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS) {
if (activeTouchId >= 0) {
// Collapse all spots into one point at the pointer location.
@@ -3648,6 +3741,11 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when,
mPointerGesture.activeGestureId);
mPointerGesture.currentGestureIdToIndex[
mPointerGesture.activeGestureId] = 0;
+ mPointerGesture.currentGestureProperties[0].clear();
+ mPointerGesture.currentGestureProperties[0].id =
+ mPointerGesture.activeGestureId;
+ mPointerGesture.currentGestureProperties[0].toolType =
+ AMOTION_EVENT_TOOL_TYPE_INDIRECT_FINGER;
mPointerGesture.currentGestureCoords[0].clear();
mPointerGesture.currentGestureCoords[0].setAxisValue(
AMOTION_EVENT_AXIS_X, mPointerGesture.tapX);
@@ -3656,8 +3754,6 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when,
mPointerGesture.currentGestureCoords[0].setAxisValue(
AMOTION_EVENT_AXIS_PRESSURE, 1.0f);
- mPointerController->setButtonState(BUTTON_STATE_PRIMARY);
-
if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS) {
mPointerGesture.spotGesture = PointerControllerInterface::SPOT_GESTURE_TAP;
mPointerGesture.spotIdBits.clear();
@@ -3691,8 +3787,6 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when,
mPointerGesture.currentGestureMode = PointerGesture::NEUTRAL;
mPointerGesture.currentGestureIdBits.clear();
- mPointerController->setButtonState(0);
-
if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS) {
mPointerGesture.spotGesture = PointerControllerInterface::SPOT_GESTURE_NEUTRAL;
mPointerGesture.spotIdBits.clear();
@@ -3767,14 +3861,16 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when,
mPointerGesture.currentGestureIdBits.clear();
mPointerGesture.currentGestureIdBits.markBit(mPointerGesture.activeGestureId);
mPointerGesture.currentGestureIdToIndex[mPointerGesture.activeGestureId] = 0;
+ mPointerGesture.currentGestureProperties[0].clear();
+ mPointerGesture.currentGestureProperties[0].id = mPointerGesture.activeGestureId;
+ mPointerGesture.currentGestureProperties[0].toolType =
+ AMOTION_EVENT_TOOL_TYPE_INDIRECT_FINGER;
mPointerGesture.currentGestureCoords[0].clear();
mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, x);
mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, y);
mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE,
down ? 1.0f : 0.0f);
- mPointerController->setButtonState(down ? BUTTON_STATE_PRIMARY : 0);
-
if (mLastTouch.pointerCount == 0 && mCurrentTouch.pointerCount != 0) {
mPointerGesture.resetTap();
mPointerGesture.tapDownTime = when;
@@ -3994,6 +4090,10 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when,
mPointerGesture.currentGestureIdBits.clear();
mPointerGesture.currentGestureIdBits.markBit(mPointerGesture.activeGestureId);
mPointerGesture.currentGestureIdToIndex[mPointerGesture.activeGestureId] = 0;
+ mPointerGesture.currentGestureProperties[0].clear();
+ mPointerGesture.currentGestureProperties[0].id = mPointerGesture.activeGestureId;
+ mPointerGesture.currentGestureProperties[0].toolType =
+ AMOTION_EVENT_TOOL_TYPE_INDIRECT_FINGER;
mPointerGesture.currentGestureCoords[0].clear();
mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
mPointerGesture.referenceGestureX);
@@ -4001,8 +4101,6 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when,
mPointerGesture.referenceGestureY);
mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 1.0f);
- mPointerController->setButtonState(BUTTON_STATE_PRIMARY);
-
if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS) {
mPointerGesture.spotGesture = PointerControllerInterface::SPOT_GESTURE_PRESS;
}
@@ -4018,6 +4116,10 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when,
mPointerGesture.currentGestureIdBits.clear();
mPointerGesture.currentGestureIdBits.markBit(mPointerGesture.activeGestureId);
mPointerGesture.currentGestureIdToIndex[mPointerGesture.activeGestureId] = 0;
+ mPointerGesture.currentGestureProperties[0].clear();
+ mPointerGesture.currentGestureProperties[0].id = mPointerGesture.activeGestureId;
+ mPointerGesture.currentGestureProperties[0].toolType =
+ AMOTION_EVENT_TOOL_TYPE_INDIRECT_FINGER;
mPointerGesture.currentGestureCoords[0].clear();
mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
mPointerGesture.referenceGestureX);
@@ -4025,8 +4127,6 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when,
mPointerGesture.referenceGestureY);
mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 1.0f);
- mPointerController->setButtonState(0); // touch is not actually following the pointer
-
if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS) {
mPointerGesture.spotGesture = PointerControllerInterface::SPOT_GESTURE_SWIPE;
}
@@ -4110,6 +4210,10 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when,
float y = (mCurrentTouch.pointers[i].y - mPointerGesture.referenceTouchY)
* mLocked.pointerGestureYZoomScale + mPointerGesture.referenceGestureY;
+ mPointerGesture.currentGestureProperties[i].clear();
+ mPointerGesture.currentGestureProperties[i].id = gestureId;
+ mPointerGesture.currentGestureProperties[i].toolType =
+ AMOTION_EVENT_TOOL_TYPE_INDIRECT_FINGER;
mPointerGesture.currentGestureCoords[i].clear();
mPointerGesture.currentGestureCoords[i].setAxisValue(
AMOTION_EVENT_AXIS_X, x);
@@ -4128,8 +4232,6 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when,
#endif
}
- mPointerController->setButtonState(0); // touch is not actually following the pointer
-
if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS) {
mPointerGesture.spotGesture = PointerControllerInterface::SPOT_GESTURE_FREEFORM;
}
@@ -4159,6 +4261,8 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when,
}
}
+ mPointerController->setButtonState(mCurrentTouch.buttonState);
+
#if DEBUG_GESTURES
LOGD("Gestures: finishPreviousGesture=%s, cancelPreviousGesture=%s, "
"currentGestureMode=%d, currentGestureIdBits=0x%08x, "
@@ -4170,9 +4274,12 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when,
uint32_t id = idBits.firstMarkedBit();
idBits.clearBit(id);
uint32_t index = mPointerGesture.currentGestureIdToIndex[id];
+ const PointerProperties& properties = mPointerGesture.currentGestureProperties[index];
const PointerCoords& coords = mPointerGesture.currentGestureCoords[index];
- LOGD(" currentGesture[%d]: index=%d, x=%0.3f, y=%0.3f, pressure=%0.3f",
- id, index, coords.getAxisValue(AMOTION_EVENT_AXIS_X),
+ LOGD(" currentGesture[%d]: index=%d, toolType=%d, "
+ "x=%0.3f, y=%0.3f, pressure=%0.3f",
+ id, index, properties.toolType,
+ coords.getAxisValue(AMOTION_EVENT_AXIS_X),
coords.getAxisValue(AMOTION_EVENT_AXIS_Y),
coords.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE));
}
@@ -4180,9 +4287,12 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when,
uint32_t id = idBits.firstMarkedBit();
idBits.clearBit(id);
uint32_t index = mPointerGesture.lastGestureIdToIndex[id];
+ const PointerProperties& properties = mPointerGesture.lastGestureProperties[index];
const PointerCoords& coords = mPointerGesture.lastGestureCoords[index];
- LOGD(" lastGesture[%d]: index=%d, x=%0.3f, y=%0.3f, pressure=%0.3f",
- id, index, coords.getAxisValue(AMOTION_EVENT_AXIS_X),
+ LOGD(" lastGesture[%d]: index=%d, toolType=%d, "
+ "x=%0.3f, y=%0.3f, pressure=%0.3f",
+ id, index, properties.toolType,
+ coords.getAxisValue(AMOTION_EVENT_AXIS_X),
coords.getAxisValue(AMOTION_EVENT_AXIS_Y),
coords.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE));
}
@@ -4196,17 +4306,18 @@ void TouchInputMapper::moveSpotsLocked() {
}
void TouchInputMapper::dispatchMotion(nsecs_t when, uint32_t policyFlags, uint32_t source,
- int32_t action, int32_t flags, uint32_t metaState, int32_t edgeFlags,
- const PointerCoords* coords, const uint32_t* idToIndex, BitSet32 idBits,
+ int32_t action, int32_t flags, int32_t metaState, int32_t buttonState, int32_t edgeFlags,
+ const PointerProperties* properties, const PointerCoords* coords,
+ const uint32_t* idToIndex, BitSet32 idBits,
int32_t changedId, float xPrecision, float yPrecision, nsecs_t downTime) {
PointerCoords pointerCoords[MAX_POINTERS];
- int32_t pointerIds[MAX_POINTERS];
+ PointerProperties pointerProperties[MAX_POINTERS];
uint32_t pointerCount = 0;
while (!idBits.isEmpty()) {
uint32_t id = idBits.firstMarkedBit();
idBits.clearBit(id);
uint32_t index = idToIndex[id];
- pointerIds[pointerCount] = id;
+ pointerProperties[pointerCount].copyFrom(properties[index]);
pointerCoords[pointerCount].copyFrom(coords[index]);
if (changedId >= 0 && id == uint32_t(changedId)) {
@@ -4233,13 +4344,14 @@ void TouchInputMapper::dispatchMotion(nsecs_t when, uint32_t policyFlags, uint32
}
getDispatcher()->notifyMotion(when, getDeviceId(), source, policyFlags,
- action, flags, metaState, edgeFlags,
- pointerCount, pointerIds, pointerCoords, xPrecision, yPrecision, downTime);
+ action, flags, metaState, buttonState, edgeFlags,
+ pointerCount, pointerProperties, pointerCoords, xPrecision, yPrecision, downTime);
}
-bool TouchInputMapper::updateMovedPointerCoords(
+bool TouchInputMapper::updateMovedPointers(const PointerProperties* inProperties,
const PointerCoords* inCoords, const uint32_t* inIdToIndex,
- PointerCoords* outCoords, const uint32_t* outIdToIndex, BitSet32 idBits) const {
+ PointerProperties* outProperties, PointerCoords* outCoords, const uint32_t* outIdToIndex,
+ BitSet32 idBits) const {
bool changed = false;
while (!idBits.isEmpty()) {
uint32_t id = idBits.firstMarkedBit();
@@ -4247,9 +4359,17 @@ bool TouchInputMapper::updateMovedPointerCoords(
uint32_t inIndex = inIdToIndex[id];
uint32_t outIndex = outIdToIndex[id];
+
+ const PointerProperties& curInProperties = inProperties[inIndex];
const PointerCoords& curInCoords = inCoords[inIndex];
+ PointerProperties& curOutProperties = outProperties[outIndex];
PointerCoords& curOutCoords = outCoords[outIndex];
+ if (curInProperties != curOutProperties) {
+ curOutProperties.copyFrom(curInProperties);
+ changed = true;
+ }
+
if (curInCoords != curOutCoords) {
curOutCoords.copyFrom(curInCoords);
changed = true;
@@ -4267,6 +4387,15 @@ void TouchInputMapper::fadePointer() {
} // release lock
}
+int32_t TouchInputMapper::getTouchToolType(bool isStylus) const {
+ if (mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN) {
+ return isStylus ? AMOTION_EVENT_TOOL_TYPE_STYLUS : AMOTION_EVENT_TOOL_TYPE_FINGER;
+ } else {
+ return isStylus ? AMOTION_EVENT_TOOL_TYPE_INDIRECT_STYLUS
+ : AMOTION_EVENT_TOOL_TYPE_INDIRECT_FINGER;
+ }
+}
+
bool TouchInputMapper::isPointInsideSurfaceLocked(int32_t x, int32_t y) {
return x >= mRawAxes.x.minValue && x <= mRawAxes.x.maxValue
&& y >= mRawAxes.y.minValue && y <= mRawAxes.y.maxValue;
@@ -4927,7 +5056,7 @@ void SingleTouchInputMapper::process(const RawEvent* rawEvent) {
break;
default:
if (mParameters.deviceType == Parameters::DEVICE_TYPE_POINTER) {
- uint32_t buttonState = getButtonStateForScanCode(rawEvent->scanCode);
+ int32_t buttonState = getButtonStateForScanCode(rawEvent->scanCode);
if (buttonState) {
if (rawEvent->value) {
mAccumulator.buttonDown |= buttonState;
@@ -5015,6 +5144,7 @@ void SingleTouchInputMapper::sync(nsecs_t when) {
mCurrentTouch.pointers[0].toolMajor = mToolWidth;
mCurrentTouch.pointers[0].toolMinor = mToolWidth;
mCurrentTouch.pointers[0].orientation = 0;
+ mCurrentTouch.pointers[0].isStylus = false; // TODO: Set stylus
mCurrentTouch.idToIndex[0] = 0;
mCurrentTouch.idBits.markBit(0);
mCurrentTouch.buttonState = mButtonState;
@@ -5060,7 +5190,7 @@ void MultiTouchInputMapper::process(const RawEvent* rawEvent) {
switch (rawEvent->type) {
case EV_KEY: {
if (mParameters.deviceType == Parameters::DEVICE_TYPE_POINTER) {
- uint32_t buttonState = getButtonStateForScanCode(rawEvent->scanCode);
+ int32_t buttonState = getButtonStateForScanCode(rawEvent->scanCode);
if (buttonState) {
if (rawEvent->value) {
mAccumulator.buttonDown |= buttonState;
@@ -5221,6 +5351,8 @@ void MultiTouchInputMapper::sync(nsecs_t when) {
outPointer.orientation = 0;
}
+ outPointer.isStylus = false; // TODO: Handle stylus
+
// Assign pointer id using tracking id if available.
if (havePointerIds) {
if (fields & Accumulator::FIELD_ABS_MT_TRACKING_ID) {
@@ -5531,6 +5663,12 @@ void JoystickInputMapper::sync(nsecs_t when, bool force) {
}
int32_t metaState = mContext->getGlobalMetaState();
+ int32_t buttonState = 0;
+
+ PointerProperties pointerProperties;
+ pointerProperties.clear();
+ pointerProperties.id = 0;
+ pointerProperties.toolType = AMOTION_EVENT_TOOL_TYPE_UNKNOWN;
PointerCoords pointerCoords;
pointerCoords.clear();
@@ -5550,10 +5688,9 @@ void JoystickInputMapper::sync(nsecs_t when, bool force) {
// TODO: Use the input device configuration to control this behavior more finely.
uint32_t policyFlags = 0;
- int32_t pointerId = 0;
getDispatcher()->notifyMotion(when, getDeviceId(), AINPUT_SOURCE_JOYSTICK, policyFlags,
- AMOTION_EVENT_ACTION_MOVE, 0, metaState, AMOTION_EVENT_EDGE_FLAG_NONE,
- 1, &pointerId, &pointerCoords, 0, 0, 0);
+ AMOTION_EVENT_ACTION_MOVE, 0, metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
+ 1, &pointerProperties, &pointerCoords, 0, 0, 0);
}
bool JoystickInputMapper::filterAxes(bool force) {
diff --git a/services/input/InputReader.h b/services/input/InputReader.h
index 0485617..62ac4b2 100644
--- a/services/input/InputReader.h
+++ b/services/input/InputReader.h
@@ -540,7 +540,7 @@ private:
sp<PointerControllerInterface> mPointerController;
struct LockedState {
- uint32_t buttonState;
+ int32_t buttonState;
nsecs_t downTime;
} mLocked;
@@ -602,6 +602,7 @@ protected:
int32_t toolMajor;
int32_t toolMinor;
int32_t orientation;
+ bool isStylus;
inline bool operator== (const PointerData& other) const {
return id == other.id
@@ -625,7 +626,7 @@ protected:
PointerData pointers[MAX_POINTERS];
BitSet32 idBits;
uint32_t idToIndex[MAX_POINTER_ID + 1];
- uint32_t buttonState;
+ int32_t buttonState;
void copyFrom(const TouchData& other) {
pointerCount = other.pointerCount;
@@ -774,9 +775,11 @@ protected:
// Current and previous touch sample data.
TouchData mCurrentTouch;
+ PointerProperties mCurrentTouchProperties[MAX_POINTERS];
PointerCoords mCurrentTouchCoords[MAX_POINTERS];
TouchData mLastTouch;
+ PointerProperties mLastTouchProperties[MAX_POINTERS];
PointerCoords mLastTouchCoords[MAX_POINTERS];
// The time the primary pointer last went down.
@@ -987,11 +990,13 @@ private:
Mode currentGestureMode;
BitSet32 currentGestureIdBits;
uint32_t currentGestureIdToIndex[MAX_POINTER_ID + 1];
+ PointerProperties currentGestureProperties[MAX_POINTERS];
PointerCoords currentGestureCoords[MAX_POINTERS];
Mode lastGestureMode;
BitSet32 lastGestureIdBits;
uint32_t lastGestureIdToIndex[MAX_POINTER_ID + 1];
+ PointerProperties lastGestureProperties[MAX_POINTERS];
PointerCoords lastGestureCoords[MAX_POINTERS];
// Pointer coords and ids for the current spots.
@@ -1068,17 +1073,22 @@ private:
// method will take care of setting the index and transmuting the action to DOWN or UP
// it is the first / last pointer to go down / up.
void dispatchMotion(nsecs_t when, uint32_t policyFlags, uint32_t source,
- int32_t action, int32_t flags, uint32_t metaState, int32_t edgeFlags,
- const PointerCoords* coords, const uint32_t* idToIndex, BitSet32 idBits,
+ int32_t action, int32_t flags, int32_t metaState, int32_t buttonState,
+ int32_t edgeFlags,
+ const PointerProperties* properties, const PointerCoords* coords,
+ const uint32_t* idToIndex, BitSet32 idBits,
int32_t changedId, float xPrecision, float yPrecision, nsecs_t downTime);
- // Updates pointer coords for pointers with specified ids that have moved.
+ // Updates pointer coords and properties for pointers with specified ids that have moved.
// Returns true if any of them changed.
- bool updateMovedPointerCoords(const PointerCoords* inCoords, const uint32_t* inIdToIndex,
- PointerCoords* outCoords, const uint32_t* outIdToIndex, BitSet32 idBits) const;
+ bool updateMovedPointers(const PointerProperties* inProperties,
+ const PointerCoords* inCoords, const uint32_t* inIdToIndex,
+ PointerProperties* outProperties, PointerCoords* outCoords,
+ const uint32_t* outIdToIndex, BitSet32 idBits) const;
void suppressSwipeOntoVirtualKeys(nsecs_t when);
+ int32_t getTouchToolType(bool isStylus) const;
bool isPointInsideSurfaceLocked(int32_t x, int32_t y);
const VirtualKey* findVirtualKeyHitLocked(int32_t x, int32_t y);
@@ -1134,7 +1144,7 @@ private:
int32_t mY;
int32_t mPressure;
int32_t mToolWidth;
- uint32_t mButtonState;
+ int32_t mButtonState;
void initialize();
@@ -1198,7 +1208,7 @@ private:
}
} mAccumulator;
- uint32_t mButtonState;
+ int32_t mButtonState;
void initialize();
diff --git a/services/input/PointerController.cpp b/services/input/PointerController.cpp
index ffef720..b87c98d 100644
--- a/services/input/PointerController.cpp
+++ b/services/input/PointerController.cpp
@@ -137,7 +137,7 @@ void PointerController::move(float deltaX, float deltaY) {
setPositionLocked(mLocked.pointerX + deltaX, mLocked.pointerY + deltaY);
}
-void PointerController::setButtonState(uint32_t buttonState) {
+void PointerController::setButtonState(int32_t buttonState) {
#if DEBUG_POINTER_UPDATES
LOGD("Set button state 0x%08x", buttonState);
#endif
@@ -148,7 +148,7 @@ void PointerController::setButtonState(uint32_t buttonState) {
}
}
-uint32_t PointerController::getButtonState() const {
+int32_t PointerController::getButtonState() const {
AutoMutex _l(mLock);
return mLocked.buttonState;
diff --git a/services/input/PointerController.h b/services/input/PointerController.h
index b9184ac..c7435ee 100644
--- a/services/input/PointerController.h
+++ b/services/input/PointerController.h
@@ -53,10 +53,10 @@ public:
virtual void move(float deltaX, float deltaY) = 0;
/* Sets a mask that indicates which buttons are pressed. */
- virtual void setButtonState(uint32_t buttonState) = 0;
+ virtual void setButtonState(int32_t buttonState) = 0;
/* Gets a mask that indicates which buttons are pressed. */
- virtual uint32_t getButtonState() const = 0;
+ virtual int32_t getButtonState() const = 0;
/* Sets the absolute location of the pointer. */
virtual void setPosition(float x, float y) = 0;
@@ -183,8 +183,8 @@ public:
virtual bool getBounds(float* outMinX, float* outMinY,
float* outMaxX, float* outMaxY) const;
virtual void move(float deltaX, float deltaY);
- virtual void setButtonState(uint32_t buttonState);
- virtual uint32_t getButtonState() const;
+ virtual void setButtonState(int32_t buttonState);
+ virtual int32_t getButtonState() const;
virtual void setPosition(float x, float y);
virtual void getPosition(float* outX, float* outY) const;
virtual void fade();
@@ -258,7 +258,7 @@ private:
SpriteIcon pointerIcon;
bool pointerIconChanged;
- uint32_t buttonState;
+ int32_t buttonState;
Vector<Spot*> spots;
Vector<sp<Sprite> > recycledSprites;
diff --git a/services/input/tests/InputDispatcher_test.cpp b/services/input/tests/InputDispatcher_test.cpp
index 3650da0..3db3473 100644
--- a/services/input/tests/InputDispatcher_test.cpp
+++ b/services/input/tests/InputDispatcher_test.cpp
@@ -142,17 +142,19 @@ TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesKeyEvents) {
TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
MotionEvent event;
- int32_t pointerIds[MAX_POINTERS + 1];
+ PointerProperties pointerProperties[MAX_POINTERS + 1];
PointerCoords pointerCoords[MAX_POINTERS + 1];
for (int i = 0; i <= MAX_POINTERS; i++) {
- pointerIds[i] = i;
+ pointerProperties[i].clear();
+ pointerProperties[i].id = i;
+ pointerCoords[i].clear();
}
// Rejects undefined motion actions.
event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
- /*action*/ -1, 0, 0, AMETA_NONE, 0, 0, 0, 0,
+ /*action*/ -1, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
ARBITRARY_TIME, ARBITRARY_TIME,
- /*pointerCount*/ 1, pointerIds, pointerCoords);
+ /*pointerCount*/ 1, pointerProperties, pointerCoords);
ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
<< "Should reject motion events with undefined action.";
@@ -160,18 +162,18 @@ TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
// Rejects pointer down with invalid index.
event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
- 0, 0, AMETA_NONE, 0, 0, 0, 0,
+ 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
ARBITRARY_TIME, ARBITRARY_TIME,
- /*pointerCount*/ 1, pointerIds, pointerCoords);
+ /*pointerCount*/ 1, pointerProperties, pointerCoords);
ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
<< "Should reject motion events with pointer down index too large.";
event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
AMOTION_EVENT_ACTION_POINTER_DOWN | (-1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
- 0, 0, AMETA_NONE, 0, 0, 0, 0,
+ 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
ARBITRARY_TIME, ARBITRARY_TIME,
- /*pointerCount*/ 1, pointerIds, pointerCoords);
+ /*pointerCount*/ 1, pointerProperties, pointerCoords);
ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
<< "Should reject motion events with pointer down index too small.";
@@ -179,65 +181,65 @@ TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
// Rejects pointer up with invalid index.
event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
AMOTION_EVENT_ACTION_POINTER_UP | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
- 0, 0, AMETA_NONE, 0, 0, 0, 0,
+ 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
ARBITRARY_TIME, ARBITRARY_TIME,
- /*pointerCount*/ 1, pointerIds, pointerCoords);
+ /*pointerCount*/ 1, pointerProperties, pointerCoords);
ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
<< "Should reject motion events with pointer up index too large.";
event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
AMOTION_EVENT_ACTION_POINTER_UP | (-1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
- 0, 0, AMETA_NONE, 0, 0, 0, 0,
+ 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
ARBITRARY_TIME, ARBITRARY_TIME,
- /*pointerCount*/ 1, pointerIds, pointerCoords);
+ /*pointerCount*/ 1, pointerProperties, pointerCoords);
ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
<< "Should reject motion events with pointer up index too small.";
// Rejects motion events with invalid number of pointers.
event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
- AMOTION_EVENT_ACTION_DOWN, 0, 0, AMETA_NONE, 0, 0, 0, 0,
+ AMOTION_EVENT_ACTION_DOWN, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
ARBITRARY_TIME, ARBITRARY_TIME,
- /*pointerCount*/ 0, pointerIds, pointerCoords);
+ /*pointerCount*/ 0, pointerProperties, pointerCoords);
ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
<< "Should reject motion events with 0 pointers.";
event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
- AMOTION_EVENT_ACTION_DOWN, 0, 0, AMETA_NONE, 0, 0, 0, 0,
+ AMOTION_EVENT_ACTION_DOWN, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
ARBITRARY_TIME, ARBITRARY_TIME,
- /*pointerCount*/ MAX_POINTERS + 1, pointerIds, pointerCoords);
+ /*pointerCount*/ MAX_POINTERS + 1, pointerProperties, pointerCoords);
ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
<< "Should reject motion events with more than MAX_POINTERS pointers.";
// Rejects motion events with invalid pointer ids.
- pointerIds[0] = -1;
+ pointerProperties[0].id = -1;
event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
- AMOTION_EVENT_ACTION_DOWN, 0, 0, AMETA_NONE, 0, 0, 0, 0,
+ AMOTION_EVENT_ACTION_DOWN, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
ARBITRARY_TIME, ARBITRARY_TIME,
- /*pointerCount*/ 1, pointerIds, pointerCoords);
+ /*pointerCount*/ 1, pointerProperties, pointerCoords);
ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
<< "Should reject motion events with pointer ids less than 0.";
- pointerIds[0] = MAX_POINTER_ID + 1;
+ pointerProperties[0].id = MAX_POINTER_ID + 1;
event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
- AMOTION_EVENT_ACTION_DOWN, 0, 0, AMETA_NONE, 0, 0, 0, 0,
+ AMOTION_EVENT_ACTION_DOWN, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
ARBITRARY_TIME, ARBITRARY_TIME,
- /*pointerCount*/ 1, pointerIds, pointerCoords);
+ /*pointerCount*/ 1, pointerProperties, pointerCoords);
ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
<< "Should reject motion events with pointer ids greater than MAX_POINTER_ID.";
// Rejects motion events with duplicate pointer ids.
- pointerIds[0] = 1;
- pointerIds[1] = 1;
+ pointerProperties[0].id = 1;
+ pointerProperties[1].id = 1;
event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
- AMOTION_EVENT_ACTION_DOWN, 0, 0, AMETA_NONE, 0, 0, 0, 0,
+ AMOTION_EVENT_ACTION_DOWN, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
ARBITRARY_TIME, ARBITRARY_TIME,
- /*pointerCount*/ 2, pointerIds, pointerCoords);
+ /*pointerCount*/ 2, pointerProperties, pointerCoords);
ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
<< "Should reject motion events with duplicate pointer ids.";
diff --git a/services/input/tests/InputReader_test.cpp b/services/input/tests/InputReader_test.cpp
index 54bb9d7..f5d7ae8 100644
--- a/services/input/tests/InputReader_test.cpp
+++ b/services/input/tests/InputReader_test.cpp
@@ -77,10 +77,10 @@ private:
virtual void move(float deltaX, float deltaY) {
}
- virtual void setButtonState(uint32_t buttonState) {
+ virtual void setButtonState(int32_t buttonState) {
}
- virtual uint32_t getButtonState() const {
+ virtual int32_t getButtonState() const {
return 0;
}
@@ -236,9 +236,10 @@ public:
int32_t action;
int32_t flags;
int32_t metaState;
+ int32_t buttonState;
int32_t edgeFlags;
uint32_t pointerCount;
- Vector<int32_t> pointerIds;
+ Vector<PointerProperties> pointerProperties;
Vector<PointerCoords> pointerCoords;
float xPrecision;
float yPrecision;
@@ -337,8 +338,9 @@ private:
virtual void notifyMotion(nsecs_t eventTime, int32_t deviceId, uint32_t source,
uint32_t policyFlags, int32_t action, int32_t flags,
- int32_t metaState, int32_t edgeFlags,
- uint32_t pointerCount, const int32_t* pointerIds, const PointerCoords* pointerCoords,
+ int32_t metaState, int32_t buttonState, int32_t edgeFlags,
+ uint32_t pointerCount, const PointerProperties* pointerProperties,
+ const PointerCoords* pointerCoords,
float xPrecision, float yPrecision, nsecs_t downTime) {
NotifyMotionArgs args;
args.eventTime = eventTime;
@@ -348,10 +350,11 @@ private:
args.action = action;
args.flags = flags;
args.metaState = metaState;
+ args.buttonState = buttonState;
args.edgeFlags = edgeFlags;
args.pointerCount = pointerCount;
- args.pointerIds.clear();
- args.pointerIds.appendArray(pointerIds, pointerCount);
+ args.pointerProperties.clear();
+ args.pointerProperties.appendArray(pointerProperties, pointerCount);
args.pointerCoords.clear();
args.pointerCoords.appendArray(pointerCoords, pointerCount);
args.xPrecision = xPrecision;
@@ -2104,9 +2107,11 @@ TEST_F(CursorInputMapperTest, Process_ShouldSetAllFieldsAndIncludeGlobalMetaStat
ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, args.action);
ASSERT_EQ(0, args.flags);
ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, args.metaState);
+ ASSERT_EQ(AMOTION_EVENT_BUTTON_PRIMARY, args.buttonState);
ASSERT_EQ(0, args.edgeFlags);
ASSERT_EQ(uint32_t(1), args.pointerCount);
- ASSERT_EQ(0, args.pointerIds[0]);
+ ASSERT_EQ(0, args.pointerProperties[0].id);
+ ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_MOUSE, args.pointerProperties[0].toolType);
ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f));
ASSERT_EQ(TRACKBALL_MOVEMENT_THRESHOLD, args.xPrecision);
@@ -2123,9 +2128,11 @@ TEST_F(CursorInputMapperTest, Process_ShouldSetAllFieldsAndIncludeGlobalMetaStat
ASSERT_EQ(AMOTION_EVENT_ACTION_UP, args.action);
ASSERT_EQ(0, args.flags);
ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, args.metaState);
+ ASSERT_EQ(0, args.buttonState);
ASSERT_EQ(0, args.edgeFlags);
ASSERT_EQ(uint32_t(1), args.pointerCount);
- ASSERT_EQ(0, args.pointerIds[0]);
+ ASSERT_EQ(0, args.pointerProperties[0].id);
+ ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_MOUSE, args.pointerProperties[0].toolType);
ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f));
ASSERT_EQ(TRACKBALL_MOVEMENT_THRESHOLD, args.xPrecision);
@@ -2756,9 +2763,11 @@ TEST_F(SingleTouchInputMapperTest, Process_WhenVirtualKeyIsPressedAndMovedOutOfB
ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
ASSERT_EQ(0, motionArgs.flags);
ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
+ ASSERT_EQ(0, motionArgs.buttonState);
ASSERT_EQ(0, motionArgs.edgeFlags);
ASSERT_EQ(size_t(1), motionArgs.pointerCount);
- ASSERT_EQ(0, motionArgs.pointerIds[0]);
+ ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
+ ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType);
ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0));
ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
@@ -2778,9 +2787,11 @@ TEST_F(SingleTouchInputMapperTest, Process_WhenVirtualKeyIsPressedAndMovedOutOfB
ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
ASSERT_EQ(0, motionArgs.flags);
ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
+ ASSERT_EQ(0, motionArgs.buttonState);
ASSERT_EQ(0, motionArgs.edgeFlags);
ASSERT_EQ(size_t(1), motionArgs.pointerCount);
- ASSERT_EQ(0, motionArgs.pointerIds[0]);
+ ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
+ ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType);
ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0));
ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
@@ -2799,9 +2810,11 @@ TEST_F(SingleTouchInputMapperTest, Process_WhenVirtualKeyIsPressedAndMovedOutOfB
ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
ASSERT_EQ(0, motionArgs.flags);
ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
+ ASSERT_EQ(0, motionArgs.buttonState);
ASSERT_EQ(0, motionArgs.edgeFlags);
ASSERT_EQ(size_t(1), motionArgs.pointerCount);
- ASSERT_EQ(0, motionArgs.pointerIds[0]);
+ ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
+ ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType);
ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0));
ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
@@ -2847,9 +2860,11 @@ TEST_F(SingleTouchInputMapperTest, Process_WhenTouchStartsOutsideDisplayAndMoves
ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
ASSERT_EQ(0, motionArgs.flags);
ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
+ ASSERT_EQ(0, motionArgs.buttonState);
ASSERT_EQ(0, motionArgs.edgeFlags);
ASSERT_EQ(size_t(1), motionArgs.pointerCount);
- ASSERT_EQ(0, motionArgs.pointerIds[0]);
+ ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
+ ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType);
ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0));
ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
@@ -2868,9 +2883,11 @@ TEST_F(SingleTouchInputMapperTest, Process_WhenTouchStartsOutsideDisplayAndMoves
ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
ASSERT_EQ(0, motionArgs.flags);
ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
+ ASSERT_EQ(0, motionArgs.buttonState);
ASSERT_EQ(0, motionArgs.edgeFlags);
ASSERT_EQ(size_t(1), motionArgs.pointerCount);
- ASSERT_EQ(0, motionArgs.pointerIds[0]);
+ ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
+ ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType);
ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0));
ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
@@ -2908,9 +2925,11 @@ TEST_F(SingleTouchInputMapperTest, Process_NormalSingleTouchGesture) {
ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
ASSERT_EQ(0, motionArgs.flags);
ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
+ ASSERT_EQ(0, motionArgs.buttonState);
ASSERT_EQ(0, motionArgs.edgeFlags);
ASSERT_EQ(size_t(1), motionArgs.pointerCount);
- ASSERT_EQ(0, motionArgs.pointerIds[0]);
+ ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
+ ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType);
ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0));
ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
@@ -2931,9 +2950,11 @@ TEST_F(SingleTouchInputMapperTest, Process_NormalSingleTouchGesture) {
ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
ASSERT_EQ(0, motionArgs.flags);
ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
+ ASSERT_EQ(0, motionArgs.buttonState);
ASSERT_EQ(0, motionArgs.edgeFlags);
ASSERT_EQ(size_t(1), motionArgs.pointerCount);
- ASSERT_EQ(0, motionArgs.pointerIds[0]);
+ ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
+ ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType);
ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0));
ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
@@ -2952,9 +2973,11 @@ TEST_F(SingleTouchInputMapperTest, Process_NormalSingleTouchGesture) {
ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
ASSERT_EQ(0, motionArgs.flags);
ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
+ ASSERT_EQ(0, motionArgs.buttonState);
ASSERT_EQ(0, motionArgs.edgeFlags);
ASSERT_EQ(size_t(1), motionArgs.pointerCount);
- ASSERT_EQ(0, motionArgs.pointerIds[0]);
+ ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
+ ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType);
ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0));
ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
@@ -3215,9 +3238,11 @@ TEST_F(MultiTouchInputMapperTest, Process_NormalMultiTouchGesture_WithoutTrackin
ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
ASSERT_EQ(0, motionArgs.flags);
ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
+ ASSERT_EQ(0, motionArgs.buttonState);
ASSERT_EQ(0, motionArgs.edgeFlags);
ASSERT_EQ(size_t(1), motionArgs.pointerCount);
- ASSERT_EQ(0, motionArgs.pointerIds[0]);
+ ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
+ ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType);
ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0));
ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
@@ -3233,10 +3258,13 @@ TEST_F(MultiTouchInputMapperTest, Process_NormalMultiTouchGesture_WithoutTrackin
motionArgs.action);
ASSERT_EQ(0, motionArgs.flags);
ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
+ ASSERT_EQ(0, motionArgs.buttonState);
ASSERT_EQ(0, motionArgs.edgeFlags);
ASSERT_EQ(size_t(2), motionArgs.pointerCount);
- ASSERT_EQ(0, motionArgs.pointerIds[0]);
- ASSERT_EQ(1, motionArgs.pointerIds[1]);
+ ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
+ ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType);
+ ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
+ ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[1].toolType);
ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0));
ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
@@ -3261,10 +3289,13 @@ TEST_F(MultiTouchInputMapperTest, Process_NormalMultiTouchGesture_WithoutTrackin
ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
ASSERT_EQ(0, motionArgs.flags);
ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
+ ASSERT_EQ(0, motionArgs.buttonState);
ASSERT_EQ(0, motionArgs.edgeFlags);
ASSERT_EQ(size_t(2), motionArgs.pointerCount);
- ASSERT_EQ(0, motionArgs.pointerIds[0]);
- ASSERT_EQ(1, motionArgs.pointerIds[1]);
+ ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
+ ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType);
+ ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
+ ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[1].toolType);
ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0));
ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
@@ -3288,10 +3319,13 @@ TEST_F(MultiTouchInputMapperTest, Process_NormalMultiTouchGesture_WithoutTrackin
motionArgs.action);
ASSERT_EQ(0, motionArgs.flags);
ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
+ ASSERT_EQ(0, motionArgs.buttonState);
ASSERT_EQ(0, motionArgs.edgeFlags);
ASSERT_EQ(size_t(2), motionArgs.pointerCount);
- ASSERT_EQ(0, motionArgs.pointerIds[0]);
- ASSERT_EQ(1, motionArgs.pointerIds[1]);
+ ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
+ ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType);
+ ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
+ ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[1].toolType);
ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0));
ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
@@ -3308,9 +3342,11 @@ TEST_F(MultiTouchInputMapperTest, Process_NormalMultiTouchGesture_WithoutTrackin
ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
ASSERT_EQ(0, motionArgs.flags);
ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
+ ASSERT_EQ(0, motionArgs.buttonState);
ASSERT_EQ(0, motionArgs.edgeFlags);
ASSERT_EQ(size_t(1), motionArgs.pointerCount);
- ASSERT_EQ(1, motionArgs.pointerIds[0]);
+ ASSERT_EQ(1, motionArgs.pointerProperties[0].id);
+ ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType);
ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0));
ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
@@ -3331,9 +3367,11 @@ TEST_F(MultiTouchInputMapperTest, Process_NormalMultiTouchGesture_WithoutTrackin
ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
ASSERT_EQ(0, motionArgs.flags);
ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
+ ASSERT_EQ(0, motionArgs.buttonState);
ASSERT_EQ(0, motionArgs.edgeFlags);
ASSERT_EQ(size_t(1), motionArgs.pointerCount);
- ASSERT_EQ(1, motionArgs.pointerIds[0]);
+ ASSERT_EQ(1, motionArgs.pointerProperties[0].id);
+ ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType);
ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0));
ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
@@ -3357,10 +3395,13 @@ TEST_F(MultiTouchInputMapperTest, Process_NormalMultiTouchGesture_WithoutTrackin
motionArgs.action);
ASSERT_EQ(0, motionArgs.flags);
ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
+ ASSERT_EQ(0, motionArgs.buttonState);
ASSERT_EQ(0, motionArgs.edgeFlags);
ASSERT_EQ(size_t(2), motionArgs.pointerCount);
- ASSERT_EQ(0, motionArgs.pointerIds[0]);
- ASSERT_EQ(1, motionArgs.pointerIds[1]);
+ ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
+ ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType);
+ ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
+ ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[1].toolType);
ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0));
ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
@@ -3384,10 +3425,13 @@ TEST_F(MultiTouchInputMapperTest, Process_NormalMultiTouchGesture_WithoutTrackin
motionArgs.action);
ASSERT_EQ(0, motionArgs.flags);
ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
+ ASSERT_EQ(0, motionArgs.buttonState);
ASSERT_EQ(0, motionArgs.edgeFlags);
ASSERT_EQ(size_t(2), motionArgs.pointerCount);
- ASSERT_EQ(0, motionArgs.pointerIds[0]);
- ASSERT_EQ(1, motionArgs.pointerIds[1]);
+ ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
+ ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType);
+ ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
+ ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[1].toolType);
ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0));
ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
@@ -3404,9 +3448,11 @@ TEST_F(MultiTouchInputMapperTest, Process_NormalMultiTouchGesture_WithoutTrackin
ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
ASSERT_EQ(0, motionArgs.flags);
ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
+ ASSERT_EQ(0, motionArgs.buttonState);
ASSERT_EQ(0, motionArgs.edgeFlags);
ASSERT_EQ(size_t(1), motionArgs.pointerCount);
- ASSERT_EQ(0, motionArgs.pointerIds[0]);
+ ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
+ ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType);
ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0));
ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
@@ -3425,9 +3471,11 @@ TEST_F(MultiTouchInputMapperTest, Process_NormalMultiTouchGesture_WithoutTrackin
ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
ASSERT_EQ(0, motionArgs.flags);
ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
+ ASSERT_EQ(0, motionArgs.buttonState);
ASSERT_EQ(0, motionArgs.edgeFlags);
ASSERT_EQ(size_t(1), motionArgs.pointerCount);
- ASSERT_EQ(0, motionArgs.pointerIds[0]);
+ ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
+ ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType);
ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0));
ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
@@ -3464,7 +3512,8 @@ TEST_F(MultiTouchInputMapperTest, Process_NormalMultiTouchGesture_WithTrackingId
ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
ASSERT_EQ(size_t(1), motionArgs.pointerCount);
- ASSERT_EQ(1, motionArgs.pointerIds[0]);
+ ASSERT_EQ(1, motionArgs.pointerProperties[0].id);
+ ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType);
ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0));
@@ -3472,8 +3521,10 @@ TEST_F(MultiTouchInputMapperTest, Process_NormalMultiTouchGesture_WithTrackingId
ASSERT_EQ(AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
motionArgs.action);
ASSERT_EQ(size_t(2), motionArgs.pointerCount);
- ASSERT_EQ(1, motionArgs.pointerIds[0]);
- ASSERT_EQ(2, motionArgs.pointerIds[1]);
+ ASSERT_EQ(1, motionArgs.pointerProperties[0].id);
+ ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType);
+ ASSERT_EQ(2, motionArgs.pointerProperties[1].id);
+ ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[1].toolType);
ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0));
ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
@@ -3492,8 +3543,10 @@ TEST_F(MultiTouchInputMapperTest, Process_NormalMultiTouchGesture_WithTrackingId
ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
ASSERT_EQ(size_t(2), motionArgs.pointerCount);
- ASSERT_EQ(1, motionArgs.pointerIds[0]);
- ASSERT_EQ(2, motionArgs.pointerIds[1]);
+ ASSERT_EQ(1, motionArgs.pointerProperties[0].id);
+ ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType);
+ ASSERT_EQ(2, motionArgs.pointerProperties[1].id);
+ ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[1].toolType);
ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0));
ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
@@ -3510,8 +3563,10 @@ TEST_F(MultiTouchInputMapperTest, Process_NormalMultiTouchGesture_WithTrackingId
ASSERT_EQ(AMOTION_EVENT_ACTION_POINTER_UP | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
motionArgs.action);
ASSERT_EQ(size_t(2), motionArgs.pointerCount);
- ASSERT_EQ(1, motionArgs.pointerIds[0]);
- ASSERT_EQ(2, motionArgs.pointerIds[1]);
+ ASSERT_EQ(1, motionArgs.pointerProperties[0].id);
+ ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType);
+ ASSERT_EQ(2, motionArgs.pointerProperties[1].id);
+ ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[1].toolType);
ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0));
ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
@@ -3520,7 +3575,8 @@ TEST_F(MultiTouchInputMapperTest, Process_NormalMultiTouchGesture_WithTrackingId
ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
ASSERT_EQ(size_t(1), motionArgs.pointerCount);
- ASSERT_EQ(2, motionArgs.pointerIds[0]);
+ ASSERT_EQ(2, motionArgs.pointerProperties[0].id);
+ ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType);
ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0));
@@ -3534,7 +3590,8 @@ TEST_F(MultiTouchInputMapperTest, Process_NormalMultiTouchGesture_WithTrackingId
ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
ASSERT_EQ(size_t(1), motionArgs.pointerCount);
- ASSERT_EQ(2, motionArgs.pointerIds[0]);
+ ASSERT_EQ(2, motionArgs.pointerProperties[0].id);
+ ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType);
ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0));
@@ -3552,8 +3609,10 @@ TEST_F(MultiTouchInputMapperTest, Process_NormalMultiTouchGesture_WithTrackingId
ASSERT_EQ(AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
motionArgs.action);
ASSERT_EQ(size_t(2), motionArgs.pointerCount);
- ASSERT_EQ(2, motionArgs.pointerIds[0]);
- ASSERT_EQ(3, motionArgs.pointerIds[1]);
+ ASSERT_EQ(2, motionArgs.pointerProperties[0].id);
+ ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType);
+ ASSERT_EQ(3, motionArgs.pointerProperties[1].id);
+ ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[1].toolType);
ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0));
ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
@@ -3570,8 +3629,10 @@ TEST_F(MultiTouchInputMapperTest, Process_NormalMultiTouchGesture_WithTrackingId
ASSERT_EQ(AMOTION_EVENT_ACTION_POINTER_UP | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
motionArgs.action);
ASSERT_EQ(size_t(2), motionArgs.pointerCount);
- ASSERT_EQ(2, motionArgs.pointerIds[0]);
- ASSERT_EQ(3, motionArgs.pointerIds[1]);
+ ASSERT_EQ(2, motionArgs.pointerProperties[0].id);
+ ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType);
+ ASSERT_EQ(3, motionArgs.pointerProperties[1].id);
+ ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[1].toolType);
ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0));
ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
@@ -3580,7 +3641,8 @@ TEST_F(MultiTouchInputMapperTest, Process_NormalMultiTouchGesture_WithTrackingId
ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
ASSERT_EQ(size_t(1), motionArgs.pointerCount);
- ASSERT_EQ(3, motionArgs.pointerIds[0]);
+ ASSERT_EQ(3, motionArgs.pointerProperties[0].id);
+ ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType);
ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0));
@@ -3591,7 +3653,8 @@ TEST_F(MultiTouchInputMapperTest, Process_NormalMultiTouchGesture_WithTrackingId
ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
ASSERT_EQ(size_t(1), motionArgs.pointerCount);
- ASSERT_EQ(3, motionArgs.pointerIds[0]);
+ ASSERT_EQ(3, motionArgs.pointerProperties[0].id);
+ ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType);
ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0));
@@ -3641,7 +3704,7 @@ TEST_F(MultiTouchInputMapperTest, Process_AllAxes_WithDefaultCalibration) {
FakeInputDispatcher::NotifyMotionArgs args;
ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
- ASSERT_EQ(id, args.pointerIds[0]);
+ ASSERT_EQ(id, args.pointerProperties[0].id);
ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
x, y, pressure, size, touchMajor, touchMinor, toolMajor, toolMinor, orientation));
}
diff --git a/services/java/com/android/server/accessibility/TouchExplorer.java b/services/java/com/android/server/accessibility/TouchExplorer.java
index 4ba6060..fb97089 100644
--- a/services/java/com/android/server/accessibility/TouchExplorer.java
+++ b/services/java/com/android/server/accessibility/TouchExplorer.java
@@ -31,6 +31,7 @@ import android.view.MotionEvent;
import android.view.ViewConfiguration;
import android.view.WindowManagerPolicy;
import android.view.MotionEvent.PointerCoords;
+import android.view.MotionEvent.PointerProperties;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;
@@ -112,8 +113,13 @@ public class TouchExplorer implements Explorer {
// Temporary array for mapping new to old pointer IDs while filtering inactive pointers.
private final int [] mTempNewToOldPointerIndexMap = new int[MAX_POINTER_COUNT];
+ // Temporary array for storing PointerProperties
+ private final PointerProperties[] mTempPointerProperties =
+ PointerProperties.createArray(MAX_POINTER_COUNT);
+
// Temporary array for storing PointerCoords
- private final PointerCoords[] mTempPointerCoords= new PointerCoords[MAX_POINTER_COUNT];
+ private final PointerCoords[] mTempPointerCoords =
+ PointerCoords.createArray(MAX_POINTER_COUNT);
// The maximal distance between two pointers so they are
// considered to be performing a drag operation.
@@ -172,11 +178,6 @@ public class TouchExplorer implements Explorer {
mHandler = new Handler(context.getMainLooper());
mSendHoverDelayed = new SendHoverDelayed();
mAccessibilityManager = AccessibilityManager.getInstance(context);
-
- // Populate the temporary array with PointerCorrds to be reused.
- for (int i = 0, count = mTempPointerCoords.length; i < count; i++) {
- mTempPointerCoords[i] = new PointerCoords();
- }
}
public void clear(MotionEvent event, int policyFlags) {
@@ -574,9 +575,9 @@ public class TouchExplorer implements Explorer {
* @param policyFlags The policy flags associated with the event.
*/
private void sendDownForAllActiveNotInjectedPointers(MotionEvent prototype, int policyFlags) {
- PointerCoords[] pointerCoords = mTempPointerCoords;
- PointerTracker pointerTracker = mPointerTracker;
- int[] pointerIds = mTempPointerIds;
+ final PointerProperties[] pointerProperties = mTempPointerProperties;
+ final PointerCoords[] pointerCoords = mTempPointerCoords;
+ final PointerTracker pointerTracker = mPointerTracker;
int pointerDataIndex = 0;
final int pinterCount = prototype.getPointerCount();
@@ -593,7 +594,7 @@ public class TouchExplorer implements Explorer {
}
// Populate and inject an event for the current pointer.
- pointerIds[pointerDataIndex] = pointerId;
+ prototype.getPointerProperties(i, pointerProperties[pointerDataIndex]);
prototype.getPointerCoords(i, pointerCoords[pointerDataIndex]);
final long downTime = pointerTracker.getLastInjectedDownEventTime();
@@ -602,7 +603,8 @@ public class TouchExplorer implements Explorer {
final long pointerDownTime = SystemClock.uptimeMillis();
MotionEvent event = MotionEvent.obtain(downTime, pointerDownTime,
- action, pointerCount, pointerIds, pointerCoords, prototype.getMetaState(),
+ action, pointerCount, pointerProperties, pointerCoords,
+ prototype.getMetaState(), prototype.getButtonState(),
prototype.getXPrecision(), prototype.getYPrecision(), prototype.getDeviceId(),
prototype.getEdgeFlags(), prototype.getSource(), prototype.getFlags());
sendMotionEvent(event, policyFlags);
@@ -620,9 +622,9 @@ public class TouchExplorer implements Explorer {
* @param policyFlags The policy flags associated with the event.
*/
private void sendUpForInjectedDownPointers(MotionEvent prototype, int policyFlags) {
- PointerTracker pointerTracker = mPointerTracker;
- PointerCoords[] pointerCoords = mTempPointerCoords;
- int[] pointerIds = mTempPointerIds;
+ final PointerTracker pointerTracker = mPointerTracker;
+ final PointerProperties[] pointerProperties = mTempPointerProperties;
+ final PointerCoords[] pointerCoords = mTempPointerCoords;
int pointerDataIndex = 0;
final int pointerCount = prototype.getPointerCount();
@@ -635,7 +637,7 @@ public class TouchExplorer implements Explorer {
}
// Populate and inject event.
- pointerIds[pointerDataIndex] = pointerId;
+ prototype.getPointerProperties(i, pointerProperties[pointerDataIndex]);
prototype.getPointerCoords(i, pointerCoords[pointerDataIndex]);
final long downTime = pointerTracker.getLastInjectedDownEventTime();
@@ -644,7 +646,8 @@ public class TouchExplorer implements Explorer {
final long eventTime = SystemClock.uptimeMillis();
MotionEvent event = MotionEvent.obtain(downTime, eventTime, action,
- newPointerCount, pointerIds, pointerCoords, prototype.getMetaState(),
+ newPointerCount, pointerProperties, pointerCoords,
+ prototype.getMetaState(), prototype.getButtonState(),
prototype.getXPrecision(), prototype.getYPrecision(), prototype.getDeviceId(),
prototype.getEdgeFlags(), prototype.getSource(), prototype.getFlags());
@@ -678,8 +681,8 @@ public class TouchExplorer implements Explorer {
}
// Filter out inactive pointers from the event and inject it.
- PointerCoords[] pointerCoords = mTempPointerCoords;
- int[] pointerIds = mTempPointerIds;
+ final PointerProperties[] pointerProperties = mTempPointerProperties;
+ final PointerCoords[] pointerCoords = mTempPointerCoords;
int [] newToOldPointerIndexMap = mTempNewToOldPointerIndexMap;
int newPointerIndex = 0;
int actionIndex = prototype.getActionIndex();
@@ -698,7 +701,7 @@ public class TouchExplorer implements Explorer {
}
newToOldPointerIndexMap[newPointerIndex] = oldPointerIndex;
- pointerIds[newPointerIndex] = pointerId;
+ prototype.getPointerProperties(oldPointerIndex, pointerProperties[newPointerIndex]);
prototype.getPointerCoords(oldPointerIndex, pointerCoords[newPointerIndex]);
newPointerIndex++;
@@ -714,7 +717,8 @@ public class TouchExplorer implements Explorer {
final int action = computeInjectionAction(prototype.getActionMasked(), actionIndex);
final int newPointerCount = newPointerIndex;
MotionEvent prunedEvent = MotionEvent.obtain(downTime, prototype.getEventTime(), action,
- newPointerCount, pointerIds, pointerCoords, prototype.getMetaState(),
+ newPointerCount, pointerProperties, pointerCoords,
+ prototype.getMetaState(), prototype.getButtonState(),
prototype.getXPrecision(), prototype.getYPrecision(), prototype.getDeviceId(),
prototype.getEdgeFlags(), prototype.getSource(),prototype.getFlags());
@@ -743,18 +747,19 @@ public class TouchExplorer implements Explorer {
* @param policyFlags The policy flags associated with the event.
*/
private void sendDragEvent(MotionEvent prototype, int action, int policyFlags) {
- PointerCoords[] pointerCoords = mTempPointerCoords;
- int[] pointerIds = mTempPointerIds;
+ final PointerProperties[] pointerProperties = mTempPointerProperties;
+ final PointerCoords[] pointerCoords = mTempPointerCoords;
final int pointerId = mDraggingPointerId;
final int pointerIndex = prototype.findPointerIndex(pointerId);
// Populate the event with the date of the dragging pointer and inject it.
- pointerIds[0] = pointerId;
+ prototype.getPointerProperties(pointerIndex, pointerProperties[0]);
prototype.getPointerCoords(pointerIndex, pointerCoords[0]);
MotionEvent event = MotionEvent.obtain(prototype.getDownTime(),
- prototype.getEventTime(), action, 1, pointerIds, pointerCoords,
- prototype.getMetaState(), prototype.getXPrecision(), prototype.getYPrecision(),
+ prototype.getEventTime(), action, 1, pointerProperties, pointerCoords,
+ prototype.getMetaState(), prototype.getButtonState(),
+ prototype.getXPrecision(), prototype.getYPrecision(),
prototype.getDeviceId(), prototype.getEdgeFlags(), prototype.getSource(),
prototype.getFlags());
@@ -769,32 +774,27 @@ public class TouchExplorer implements Explorer {
* @param policyFlags The policy flags associated with the event.
*/
private void sendActionDownAndUp(MotionEvent prototype, int policyFlags) {
- PointerCoords[] pointerCoords = mTempPointerCoords;
- int[] pointerIds = mTempPointerIds;
+ final PointerProperties[] pointerProperties = mTempPointerProperties;
+ final PointerCoords[] pointerCoords = mTempPointerCoords;
final int pointerId = mPointerTracker.getLastReceivedUpPointerId();
final int pointerIndex = prototype.findPointerIndex(pointerId);
// Send down.
- pointerIds[0] = pointerId;
+ prototype.getPointerProperties(pointerIndex, pointerProperties[0]);
prototype.getPointerCoords(pointerIndex, pointerCoords[0]);
final long downTime = SystemClock.uptimeMillis();
-
- MotionEvent downEvent = MotionEvent.obtain(downTime, downTime, MotionEvent.ACTION_DOWN,
- 1, mTempPointerIds, mTempPointerCoords, prototype.getMetaState(),
+ MotionEvent event = MotionEvent.obtain(downTime, downTime, MotionEvent.ACTION_DOWN,
+ 1, pointerProperties, pointerCoords,
+ prototype.getMetaState(), prototype.getButtonState(),
prototype.getXPrecision(), prototype.getYPrecision(), prototype.getDeviceId(),
prototype.getEdgeFlags(), prototype.getSource(), prototype.getFlags());
-
- // Clone the down event before recycling it.
- MotionEvent upEvent = MotionEvent.obtain(downEvent);
-
- sendMotionEvent(downEvent, policyFlags);
- downEvent.recycle();
+ sendMotionEvent(event, policyFlags);
// Send up.
- upEvent.setAction(MotionEvent.ACTION_UP);
- sendMotionEvent(upEvent, policyFlags);
- upEvent.recycle();
+ event.setAction(MotionEvent.ACTION_UP);
+ sendMotionEvent(event, policyFlags);
+ event.recycle();
}
/**
@@ -807,21 +807,20 @@ public class TouchExplorer implements Explorer {
*/
private void sendHoverEvent(MotionEvent prototype, int action, int pointerIndex, int
policyFlags) {
- PointerCoords[] pointerCoords = mTempPointerCoords;
- int[] pointerIds = mTempPointerIds;
+ final PointerProperties[] pointerProperties = mTempPointerProperties;
+ final PointerCoords[] pointerCoords = mTempPointerCoords;
- // Keep only data relevant to a hover event.
- pointerIds[0] = prototype.getPointerId(pointerIndex);
- pointerCoords[0].clear();
- pointerCoords[0].x = prototype.getX(pointerIndex);
- pointerCoords[0].y = prototype.getY(pointerIndex);
+ prototype.getPointerProperties(pointerIndex, pointerProperties[0]);
+ prototype.getPointerCoords(pointerIndex, pointerCoords[0]);
final long downTime = mPointerTracker.getLastInjectedDownEventTime();
// Populate and inject a hover event.
MotionEvent hoverEvent = MotionEvent.obtain(downTime, prototype.getEventTime(), action,
- 1, pointerIds, pointerCoords, 0, 0, 0, prototype.getDeviceId(), 0,
- prototype.getSource(), 0);
+ 1, pointerProperties, pointerCoords,
+ prototype.getMetaState(), prototype.getButtonState(),
+ prototype.getXPrecision(), prototype.getYPrecision(), prototype.getDeviceId(),
+ prototype.getEdgeFlags(), prototype.getSource(), prototype.getFlags());
sendMotionEvent(hoverEvent, policyFlags);
hoverEvent.recycle();