summaryrefslogtreecommitdiff
path: root/core/java/android/view/MotionEvent.java
diff options
context:
space:
mode:
authorGarfield Tan <xutan@google.com>2019-07-15 14:00:35 -0700
committerGarfield Tan <xutan@google.com>2019-07-30 09:22:27 -0700
commit1da8628ae3edf2945dfa2bc1ec43dc848d4ffffb (patch)
tree76681508c072633d7a15d210dbc5fcebdc78d139 /core/java/android/view/MotionEvent.java
parent2c79b41c80028a1ff57e60fabdedb8db5438f4db (diff)
Add cursor position to synthesized events.
Synthesized events consist of injected, split and clamped events. Instead of letting caller specify it, we fill cursor position fields by deriving from pointers. Thus we can maintain the property between pointer coodinates and cursor position. If there is need we can add a new obtain method later as well anyway. I decided to update the value for split events because it would be unnatural to have a out of bound cursor position when a gesture crosses view boundaries, but ultimately we probably shouldn't split mouse events. Nevertheless that's out of the scope of this CL and I chose to be on the safe side at this moment. Bug: 134788085 Bug: 136607870 Test: atest TooltipTest#testMouseHoverTooltipWithHoverListener Test: atest MotionEventTest (and select running all candidates) Test: atest DragDropTest Change-Id: I4f3dec0f3c4c1ab2ff5cb986b94b0e007d9fe41b
Diffstat (limited to 'core/java/android/view/MotionEvent.java')
-rw-r--r--core/java/android/view/MotionEvent.java111
1 files changed, 101 insertions, 10 deletions
diff --git a/core/java/android/view/MotionEvent.java b/core/java/android/view/MotionEvent.java
index bff3a1dba3f4..bd865c063055 100644
--- a/core/java/android/view/MotionEvent.java
+++ b/core/java/android/view/MotionEvent.java
@@ -1471,6 +1471,10 @@ public final class MotionEvent extends InputEvent implements Parcelable {
@UnsupportedAppUsage
private static final int HISTORY_CURRENT = -0x80000000;
+ // This is essentially the same as native AMOTION_EVENT_INVALID_CURSOR_POSITION as they're all
+ // NaN and we use isnan() everywhere to check validity.
+ private static final float INVALID_CURSOR_POSITION = Float.NaN;
+
private static final int MAX_RECYCLED = 10;
private static final Object gRecyclerLock = new Object();
private static int gRecyclerUsed;
@@ -1590,6 +1594,12 @@ public final class MotionEvent extends InputEvent implements Parcelable {
@CriticalNative
private static native float nativeGetYPrecision(long nativePtr);
@CriticalNative
+ private static native float nativeGetXCursorPosition(long nativePtr);
+ @CriticalNative
+ private static native float nativeGetYCursorPosition(long nativePtr);
+ @CriticalNative
+ private static native void nativeSetCursorPosition(long nativePtr, float x, float y);
+ @CriticalNative
private static native long nativeGetDownTimeNanos(long nativePtr);
@CriticalNative
private static native void nativeSetDownTimeNanos(long nativePtr, long downTime);
@@ -1674,12 +1684,11 @@ public final class MotionEvent extends InputEvent implements Parcelable {
float xPrecision, float yPrecision, int deviceId,
int edgeFlags, int source, int displayId, int flags) {
MotionEvent ev = obtain();
- ev.mNativePtr = nativeInitialize(ev.mNativePtr,
- deviceId, source, displayId, action, flags, edgeFlags, metaState, buttonState,
- CLASSIFICATION_NONE, 0, 0, xPrecision, yPrecision,
+ final boolean success = ev.initialize(deviceId, source, displayId, action, flags, edgeFlags,
+ metaState, buttonState, CLASSIFICATION_NONE, 0, 0, xPrecision, yPrecision,
downTime * NS_PER_MS, eventTime * NS_PER_MS,
pointerCount, pointerProperties, pointerCoords);
- if (ev.mNativePtr == 0) {
+ if (!success) {
Log.e(TAG, "Could not initialize MotionEvent");
ev.recycle();
return null;
@@ -1859,8 +1868,7 @@ public final class MotionEvent extends InputEvent implements Parcelable {
pc[0].pressure = pressure;
pc[0].size = size;
- ev.mNativePtr = nativeInitialize(ev.mNativePtr,
- deviceId, source, displayId,
+ ev.initialize(deviceId, source, displayId,
action, 0, edgeFlags, metaState, 0 /*buttonState*/, CLASSIFICATION_NONE,
0, 0, xPrecision, yPrecision,
downTime * NS_PER_MS, eventTime * NS_PER_MS,
@@ -1958,6 +1966,22 @@ public final class MotionEvent extends InputEvent implements Parcelable {
return ev;
}
+ private boolean initialize(int deviceId, int source, int displayId, int action, int flags,
+ int edgeFlags, int metaState, int buttonState, @Classification int classification,
+ float xOffset, float yOffset, float xPrecision, float yPrecision,
+ long downTimeNanos, long eventTimeNanos,
+ int pointerCount, PointerProperties[] pointerIds, PointerCoords[] pointerCoords) {
+ mNativePtr = nativeInitialize(mNativePtr, deviceId, source, displayId, action, flags,
+ edgeFlags, metaState, buttonState, classification, xOffset, yOffset,
+ xPrecision, yPrecision, downTimeNanos, eventTimeNanos, pointerCount, pointerIds,
+ pointerCoords);
+ if (mNativePtr == 0) {
+ return false;
+ }
+ updateCursorPosition();
+ return true;
+ }
+
/** @hide */
@Override
@UnsupportedAppUsage
@@ -2015,7 +2039,11 @@ public final class MotionEvent extends InputEvent implements Parcelable {
/** {@inheritDoc} */
@Override
public final void setSource(int source) {
+ if (source == getSource()) {
+ return;
+ }
nativeSetSource(mNativePtr, source);
+ updateCursorPosition();
}
/** @hide */
@@ -2670,6 +2698,39 @@ public final class MotionEvent extends InputEvent implements Parcelable {
}
/**
+ * Returns the x coordinate of mouse cursor position when this event is
+ * reported. This value is only valid if {@link #getSource()} returns
+ * {@link InputDevice#SOURCE_MOUSE}.
+ *
+ * @hide
+ */
+ public float getXCursorPosition() {
+ return nativeGetXCursorPosition(mNativePtr);
+ }
+
+ /**
+ * Returns the y coordinate of mouse cursor position when this event is
+ * reported. This value is only valid if {@link #getSource()} returns
+ * {@link InputDevice#SOURCE_MOUSE}.
+ *
+ * @hide
+ */
+ public float getYCursorPosition() {
+ return nativeGetYCursorPosition(mNativePtr);
+ }
+
+ /**
+ * Sets cursor position to given coordinates. The coordinate in parameters should be after
+ * offsetting. In other words, the effect of this function is {@link #getXCursorPosition()} and
+ * {@link #getYCursorPosition()} will return the same value passed in the parameters.
+ *
+ * @hide
+ */
+ private void setCursorPosition(float x, float y) {
+ nativeSetCursorPosition(mNativePtr, x, y);
+ }
+
+ /**
* Returns the number of historical points in this event. These are
* movements that have occurred between this event and the previous event.
* This only applies to ACTION_MOVE events -- all other actions will have
@@ -3305,8 +3366,7 @@ public final class MotionEvent extends InputEvent implements Parcelable {
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),
+ ev.initialize(nativeGetDeviceId(mNativePtr), nativeGetSource(mNativePtr),
nativeGetDisplayId(mNativePtr),
nativeGetAction(mNativePtr), nativeGetFlags(mNativePtr),
nativeGetEdgeFlags(mNativePtr), nativeGetMetaState(mNativePtr),
@@ -3399,8 +3459,7 @@ public final class MotionEvent extends InputEvent implements Parcelable {
final long eventTimeNanos = nativeGetEventTimeNanos(mNativePtr, historyPos);
if (h == 0) {
- ev.mNativePtr = nativeInitialize(ev.mNativePtr,
- nativeGetDeviceId(mNativePtr), nativeGetSource(mNativePtr),
+ ev.initialize(nativeGetDeviceId(mNativePtr), nativeGetSource(mNativePtr),
nativeGetDisplayId(mNativePtr),
newAction, nativeGetFlags(mNativePtr),
nativeGetEdgeFlags(mNativePtr), nativeGetMetaState(mNativePtr),
@@ -3417,6 +3476,38 @@ public final class MotionEvent extends InputEvent implements Parcelable {
}
}
+ /**
+ * Calculate new cursor position for events from mouse. This is used to split, clamp and inject
+ * events.
+ *
+ * <p>If the source is mouse, it sets cursor position to the centroid of all pointers because
+ * InputReader maps multiple fingers on a touchpad to locations around cursor position in screen
+ * coordinates so that the mouse cursor is at the centroid of all pointers.
+ *
+ * <p>If the source is not mouse it sets cursor position to NaN.
+ */
+ private void updateCursorPosition() {
+ if (getSource() != InputDevice.SOURCE_MOUSE) {
+ setCursorPosition(INVALID_CURSOR_POSITION, INVALID_CURSOR_POSITION);
+ return;
+ }
+
+ float x = 0;
+ float y = 0;
+
+ final int pointerCount = getPointerCount();
+ for (int i = 0; i < pointerCount; ++i) {
+ x += getX(i);
+ y += getY(i);
+ }
+
+ // If pointer count is 0, divisions below yield NaN, which is an acceptable result for this
+ // corner case.
+ x /= pointerCount;
+ y /= pointerCount;
+ setCursorPosition(x, y);
+ }
+
@Override
public String toString() {
StringBuilder msg = new StringBuilder();