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

Commit 2b342f0a authored by Adam Powell's avatar Adam Powell
Browse files

Allow ViewGroup to split MotionEvents to multiple targets during dispatch.

Use the layout xml attribute splitMotionEvents="true" or the ViewGroup
method setMotionEventSplittingEnabled(true) to enable motion event
splitting. Rules for splitting are as follows:

* Splitting is enabled per ViewGroup. When splitting is enabled any
  MotionEvent dispatched to that ViewGroup can potentially be split
  into several and dispatched to children independently.

* Each pointer is assigned a target child view when the ACTION_DOWN or
  ACTION_POINTER_DOWN event is received. That will be the pointer's
  target until it goes up, the target returns false from onTouchEvent,
  or the MotionEvents are intercepted.

* Multiple pointers may be assigned to the same target. All pointer
  data sent to a target are bundled into a single MotionEvent. Child
  views do not need to be aware that splitting has occurred.

Change-Id: I993f838e2f6b455da9812f4742a016dfcd1c4cc9
parent 8a44bb23
Loading
Loading
Loading
Loading
+35 −0
Original line number Diff line number Diff line
@@ -8919,6 +8919,17 @@
 visibility="public"
>
</field>
<field name="splitMotionEvents"
 type="int"
 transient="false"
 volatile="false"
 value="16843567"
 static="true"
 final="true"
 deprecated="not deprecated"
 visibility="public"
>
</field>
<field name="src"
 type="int"
 transient="false"
@@ -199360,6 +199371,17 @@
 visibility="protected"
>
</method>
<method name="isMotionEventSplittingEnabled"
 return="boolean"
 abstract="false"
 native="false"
 synchronized="false"
 static="false"
 final="false"
 deprecated="not deprecated"
 visibility="public"
>
</method>
<method name="measureChild"
 return="void"
 abstract="false"
@@ -199823,6 +199845,19 @@
<parameter name="animationListener" type="android.view.animation.Animation.AnimationListener">
</parameter>
</method>
<method name="setMotionEventSplittingEnabled"
 return="void"
 abstract="false"
 native="false"
 synchronized="false"
 static="false"
 final="false"
 deprecated="not deprecated"
 visibility="public"
>
<parameter name="split" type="boolean">
</parameter>
</method>
<method name="setOnHierarchyChangeListener"
 return="void"
 abstract="false"
+1 −33
Original line number Diff line number Diff line
@@ -16,7 +16,6 @@

package android.view;

import android.graphics.Camera;
import com.android.internal.R;
import com.android.internal.view.menu.MenuBuilder;

@@ -25,6 +24,7 @@ import android.content.res.Configuration;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Camera;
import android.graphics.Canvas;
import android.graphics.Interpolator;
import android.graphics.LinearGradient;
@@ -69,7 +69,6 @@ import android.view.inputmethod.InputConnection;
import android.view.inputmethod.InputMethodManager;
import android.widget.ScrollBarDrawable;

import java.lang.ref.SoftReference;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
@@ -5418,37 +5417,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
        }
    }

    /**
     * This method detects whether the given event is inside the view and, if so,
     * handles it via the dispatchEvent(MotionEvent) method.
     *
     * @param ev The event that is being dispatched.
     * @param parentX The x location of the event in the parent's coordinates.
     * @param parentY The y location of the event in the parent's coordinates.
     * @return true if the event was inside this view, false otherwise.
     */
    boolean dispatchTouchEvent(MotionEvent ev, float parentX, float parentY) {
        float localX = parentX - mLeft;
        float localY = parentY - mTop;
        if (!hasIdentityMatrix() && mAttachInfo != null) {
            // non-identity matrix: transform the point into the view's coordinates
            final float[] localXY = mAttachInfo.mTmpTransformLocation;
            localXY[0] = localX;
            localXY[1] = localY;
            getInverseMatrix().mapPoints(localXY);
            localX = localXY[0];
            localY = localXY[1];
        }
        if (localX >= 0 && localY >= 0 && localX < (mRight - mLeft) && localY < (mBottom - mTop)) {
            // It would be safer to clone the event here but we don't for performance.
            // There are many subtle interactions in touch event dispatch; change at your own risk.
            mPrivateFlags &= ~CANCEL_NEXT_UP_EVENT;
            ev.setLocation(localX, localY);
            return dispatchTouchEvent(ev);
        }
        return false;
    }

    /**
     * Utility method to determine whether the given point, in local coordinates,
     * is inside the view, where the area of the view is expanded by the slop factor.