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

Commit 9d3bdbd6 authored by Jeff Brown's avatar Jeff Brown Committed by John Reck
Browse files

New WebView input dispatcher.

Bug: 6317798

Stuff that's better:

1. We maintain two queues in a way that ensures that WebView and
WebKit both see consistent streams of events, even in cases
where WebKit times out.  We send ACTION_CANCEL if necessary, etc.

2. All pointer events go through the same channel, including
hover and click ("touch up") events, to ensure correct ordering.

3. Given that the input events are in a separate queue, we can
force execution of all of these events whenever we like, making new
latency optimizations possible.

4. The entire history of each touch event is sent to the web
application to enable smoother interaction.

5. The web application may choose to intercept a touch event stream
at any time by issuing "prevent default".  Previously, it could only
prevent default on the initial down event.  The new behavior is more
standards compliant.

Change-Id: I42d2d045e7d44af7c54b29570f188b7400d91d4e
parent 450c75a5
Loading
Loading
Loading
Loading
+78 −0
Original line number Diff line number Diff line
@@ -2714,6 +2714,67 @@ public final class MotionEvent extends InputEvent implements Parcelable {
        nativeAddBatch(mNativePtr, eventTime * NS_PER_MS, pointerCoords, metaState);
    }

    /**
     * Adds all of the movement samples of the specified event to this one if
     * it is compatible.  To be compatible, the event must have the same device id,
     * source, action, flags, pointer count, pointer properties.
     *
     * Only applies to {@link #ACTION_MOVE} or {@link #ACTION_HOVER_MOVE} events.
     *
     * @param event The event whose movements samples should be added to this one
     * if possible.
     * @return True if batching was performed or false if batching was not possible.
     * @hide
     */
    public final boolean addBatch(MotionEvent event) {
        final int action = nativeGetAction(mNativePtr);
        if (action != ACTION_MOVE && action != ACTION_HOVER_MOVE) {
            return false;
        }
        if (action != nativeGetAction(event.mNativePtr)) {
            return false;
        }

        if (nativeGetDeviceId(mNativePtr) != nativeGetDeviceId(event.mNativePtr)
                || nativeGetSource(mNativePtr) != nativeGetSource(event.mNativePtr)
                || nativeGetFlags(mNativePtr) != nativeGetFlags(event.mNativePtr)) {
            return false;
        }

        final int pointerCount = nativeGetPointerCount(mNativePtr);
        if (pointerCount != nativeGetPointerCount(event.mNativePtr)) {
            return false;
        }

        synchronized (gSharedTempLock) {
            ensureSharedTempPointerCapacity(Math.max(pointerCount, 2));
            final PointerProperties[] pp = gSharedTempPointerProperties;
            final PointerCoords[] pc = gSharedTempPointerCoords;

            for (int i = 0; i < pointerCount; i++) {
                nativeGetPointerProperties(mNativePtr, i, pp[0]);
                nativeGetPointerProperties(event.mNativePtr, i, pp[1]);
                if (!pp[0].equals(pp[1])) {
                    return false;
                }
            }

            final int metaState = nativeGetMetaState(event.mNativePtr);
            final int historySize = nativeGetHistorySize(event.mNativePtr);
            for (int h = 0; h <= historySize; h++) {
                final int historyPos = (h == historySize ? HISTORY_CURRENT : h);

                for (int i = 0; i < pointerCount; i++) {
                    nativeGetPointerCoords(event.mNativePtr, i, historyPos, pc[i]);
                }

                final long eventTimeNanos = nativeGetEventTimeNanos(event.mNativePtr, historyPos);
                nativeAddBatch(mNativePtr, eventTimeNanos, pc, metaState);
            }
        }
        return true;
    }

    /**
     * Returns true if all points in the motion event are completely within the specified bounds.
     * @hide
@@ -3416,5 +3477,22 @@ public final class MotionEvent extends InputEvent implements Parcelable {
            id = other.id;
            toolType = other.toolType;
        }

        @Override
        public boolean equals(Object other) {
            if (other instanceof PointerProperties) {
                return equals((PointerProperties)other);
            }
            return false;
        }

        private boolean equals(PointerProperties other) {
            return other != null && id == other.id && toolType == other.toolType;
        }

        @Override
        public int hashCode() {
            return id | (toolType << 8);
        }
    }
}
+110 −954

File changed.

Preview size limit exceeded, changes collapsed.

+41 −47
Original line number Diff line number Diff line
@@ -40,6 +40,7 @@ import android.view.MotionEvent;
import android.view.SurfaceView;
import android.view.View;
import android.webkit.WebViewClassic.FocusNodeHref;
import android.webkit.WebViewInputDispatcher.WebKitCallbacks;

import junit.framework.Assert;

@@ -259,6 +260,10 @@ public final class WebViewCore {
        return mBrowserFrame;
    }

    public WebKitCallbacks getInputDispatcherCallbacks() {
        return mEventHub;
    }

    //-------------------------------------------------------------------------
    // Common methods
    //-------------------------------------------------------------------------
@@ -663,6 +668,7 @@ public final class WebViewCore {
            int x, int y);
    private native void nativeTouchUp(int nativeClass,
            int touchGeneration, int framePtr, int nodePtr, int x, int y);
    private native boolean nativeMouseClick(int nativeClass);

    private native boolean nativeHandleTouchEvent(int nativeClass, int action,
            int[] idArray, int[] xArray, int[] yArray, int count,
@@ -1025,8 +1031,8 @@ public final class WebViewCore {
            "REQUEST_CURSOR_HREF", // = 137;
            "ADD_JS_INTERFACE", // = 138;
            "LOAD_DATA", // = 139;
            "TOUCH_UP", // = 140;
            "TOUCH_EVENT", // = 141;
            "", // = 140;
            "", // = 141;
            "SET_ACTIVE", // = 142;
            "ON_PAUSE",     // = 143
            "ON_RESUME",    // = 144
@@ -1051,7 +1057,7 @@ public final class WebViewCore {
    /**
     * @hide
     */
    public class EventHub {
    public class EventHub implements WebViewInputDispatcher.WebKitCallbacks {
        // Message Ids
        static final int REVEAL_SELECTION = 96;
        static final int SCROLL_TEXT_INPUT = 99;
@@ -1096,11 +1102,6 @@ public final class WebViewCore {
        static final int ADD_JS_INTERFACE = 138;
        static final int LOAD_DATA = 139;

        // motion
        static final int TOUCH_UP = 140;
        // message used to pass UI touch events to WebCore
        static final int TOUCH_EVENT = 141;

        // Used to tell the focus controller not to draw the blinking cursor,
        // based on whether the WebView has focus and whether the WebView's
        // cursor matches the webpage's focus.
@@ -1496,45 +1497,6 @@ public final class WebViewCore {
                            nativeCloseIdleConnections(mNativeClass);
                            break;

                        case TOUCH_UP:
                            TouchUpData touchUpData = (TouchUpData) msg.obj;
                            if (touchUpData.mNativeLayer != 0) {
                                nativeScrollLayer(mNativeClass,
                                        touchUpData.mNativeLayer,
                                        touchUpData.mNativeLayerRect);
                            }
                            nativeTouchUp(mNativeClass,
                                    touchUpData.mMoveGeneration,
                                    touchUpData.mFrame, touchUpData.mNode,
                                    touchUpData.mX, touchUpData.mY);
                            break;

                        case TOUCH_EVENT: {
                            TouchEventData ted = (TouchEventData) msg.obj;
                            final int count = ted.mPoints.length;
                            int[] xArray = new int[count];
                            int[] yArray = new int[count];
                            for (int c = 0; c < count; c++) {
                                xArray[c] = ted.mPoints[c].x;
                                yArray[c] = ted.mPoints[c].y;
                            }
                            if (ted.mNativeLayer != 0) {
                                nativeScrollLayer(mNativeClass,
                                        ted.mNativeLayer, ted.mNativeLayerRect);
                            }
                            ted.mNativeResult = nativeHandleTouchEvent(
                                    mNativeClass, ted.mAction, ted.mIds, xArray,
                                    yArray, count, ted.mActionIndex,
                                    ted.mMetaState);
                            Message.obtain(
                                    mWebViewClassic.mPrivateHandler,
                                    WebViewClassic.PREVENT_TOUCH_ID,
                                    ted.mAction,
                                    ted.mNativeResult ? 1 : 0,
                                    ted).sendToTarget();
                            break;
                        }

                        case SET_ACTIVE:
                            nativeSetFocusControllerActive(mNativeClass, msg.arg1 == 1);
                            break;
@@ -1818,6 +1780,38 @@ public final class WebViewCore {
            }
        }

        @Override
        public Looper getWebKitLooper() {
            return mHandler.getLooper();
        }

        @Override
        public boolean dispatchWebKitEvent(MotionEvent event, int eventType, int flags) {
            switch (eventType) {
                case WebViewInputDispatcher.EVENT_TYPE_CLICK:
                    return nativeMouseClick(mNativeClass);

                case WebViewInputDispatcher.EVENT_TYPE_TOUCH: {
                    int count = event.getPointerCount();
                    int[] idArray = new int[count];
                    int[] xArray = new int[count];
                    int[] yArray = new int[count];
                    for (int i = 0; i < count; i++) {
                        idArray[i] = event.getPointerId(i);
                        xArray[i] = (int) event.getX(i);
                        yArray[i] = (int) event.getY(i);
                    }
                    return nativeHandleTouchEvent(mNativeClass,
                            event.getActionMasked(),
                            idArray, xArray, yArray, count,
                            event.getActionIndex(), event.getMetaState());
                }

                default:
                    return false;
            }
        }

        /**
         * Send a message internally to the queue or to the handler
         */
+1151 −0

File added.

Preview size limit exceeded, changes collapsed.