Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2b551ea6 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Add cursor position to synthesized events."

parents 30740861 1da8628a
Loading
Loading
Loading
Loading
+101 −10
Original line number Diff line number Diff line
@@ -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 */
@@ -2669,6 +2697,39 @@ public final class MotionEvent extends InputEvent implements Parcelable {
        return nativeGetYPrecision(mNativePtr);
    }

    /**
     * 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.
@@ -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();
+24 −0
Original line number Diff line number Diff line
@@ -701,6 +701,21 @@ static jfloat android_view_MotionEvent_nativeGetYPrecision(jlong nativePtr) {
    return event->getYPrecision();
}

static jfloat android_view_MotionEvent_nativeGetXCursorPosition(jlong nativePtr) {
    MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
    return event->getXCursorPosition();
}

static jfloat android_view_MotionEvent_nativeGetYCursorPosition(jlong nativePtr) {
    MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
    return event->getYCursorPosition();
}

static void android_view_MotionEvent_nativeSetCursorPosition(jlong nativePtr, jfloat x, jfloat y) {
    MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
    event->setCursorPosition(x, y);
}

static jlong android_view_MotionEvent_nativeGetDownTimeNanos(jlong nativePtr) {
    MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
    return event->getDownTime();
@@ -871,6 +886,15 @@ static const JNINativeMethod gMotionEventMethods[] = {
    { "nativeGetYPrecision",
            "(J)F",
            (void*)android_view_MotionEvent_nativeGetYPrecision },
    { "nativeGetXCursorPosition",
            "(J)F",
            (void*)android_view_MotionEvent_nativeGetXCursorPosition },
    { "nativeGetYCursorPosition",
            "(J)F",
            (void*)android_view_MotionEvent_nativeGetYCursorPosition },
    { "nativeSetCursorPosition",
            "(JFF)V",
            (void*)android_view_MotionEvent_nativeSetCursorPosition },
    { "nativeGetDownTimeNanos",
            "(J)J",
            (void*)android_view_MotionEvent_nativeGetDownTimeNanos },
+61 −0
Original line number Diff line number Diff line
@@ -17,8 +17,11 @@
package android.view;

import static android.view.MotionEvent.ACTION_DOWN;
import static android.view.MotionEvent.ACTION_POINTER_DOWN;
import static android.view.MotionEvent.TOOL_TYPE_FINGER;

import static junit.framework.Assert.assertTrue;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;

@@ -77,4 +80,62 @@ public class MotionEventTest {
                0, 0, 0, 0, 0, 0, InputDevice.SOURCE_TOUCHSCREEN, displayId, 0);
        assertNull(motionEvent);
    }

    @Test
    public void testCalculatesCursorPositionForTouchscreenEvents() {
        final MotionEvent event = MotionEvent.obtain(0 /* downTime */, 0 /* eventTime */,
                ACTION_DOWN, 30 /* x */, 50 /* y */, 0 /* metaState */);
        event.setSource(InputDevice.SOURCE_TOUCHSCREEN);

        assertTrue(Float.isNaN(event.getXCursorPosition()));
        assertTrue(Float.isNaN(event.getYCursorPosition()));
    }

    @Test
    public void testCalculatesCursorPositionForSimpleMouseEvents() {
        final MotionEvent event = MotionEvent.obtain(0 /* downTime */, 0 /* eventTime */,
                ACTION_DOWN, 30 /* x */, 50 /* y */, 0 /* metaState */);
        event.setSource(InputDevice.SOURCE_MOUSE);

        assertEquals(30, event.getXCursorPosition(), 0.1);
        assertEquals(50, event.getYCursorPosition(), 0.1);
    }

    @Test
    public void testCalculatesCursorPositionForSimpleMouseEventsWithOffset() {
        final MotionEvent event = MotionEvent.obtain(0 /* downTime */, 0 /* eventTime */,
                ACTION_DOWN, 30 /* x */, 50 /* y */, 0 /* metaState */);
        event.offsetLocation(10 /* deltaX */, 20 /* deltaY */);
        event.setSource(InputDevice.SOURCE_MOUSE);

        assertEquals(40, event.getXCursorPosition(), 0.1);
        assertEquals(70, event.getYCursorPosition(), 0.1);
    }


    @Test
    public void testCalculatesCursorPositionForMultiTouchMouseEvents() {
        final int pointerCount = 2;
        final PointerProperties[] properties = new PointerProperties[pointerCount];
        final PointerCoords[] coords = new PointerCoords[pointerCount];

        for (int i = 0; i < pointerCount; ++i) {
            properties[i] = new PointerProperties();
            properties[i].id = i;
            properties[i].toolType = MotionEvent.TOOL_TYPE_FINGER;

            coords[i] = new PointerCoords();
            coords[i].x = 20 + i * 20;
            coords[i].y = 60 - i * 20;
        }

        final MotionEvent event = MotionEvent.obtain(0 /* downTime */,
                0 /* eventTime */, ACTION_POINTER_DOWN, pointerCount, properties, coords,
                0 /* metaState */, 0 /* buttonState */, 1 /* xPrecision */, 1 /* yPrecision */,
                0 /* deviceId */, 0 /* edgeFlags */, InputDevice.SOURCE_MOUSE,
                0 /* flags */);

        assertEquals(30, event.getXCursorPosition(), 0.1);
        assertEquals(50, event.getYCursorPosition(), 0.1);
    }
}