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

Commit 9212e350 authored by Alan Viverette's avatar Alan Viverette Committed by Android (Google) Code Review
Browse files

Merge "Reconcile drag-to-open and touch event interception" into klp-dev

parents 3871fdb9 69960142
Loading
Loading
Loading
Loading
+77 −24
Original line number Original line Diff line number Diff line
@@ -32,6 +32,7 @@ import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.View;
import android.view.View.MeasureSpec;
import android.view.View.MeasureSpec;
import android.view.View.OnAttachStateChangeListener;
import android.view.View.OnTouchListener;
import android.view.View.OnTouchListener;
import android.view.ViewConfiguration;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.view.ViewGroup;
@@ -1133,18 +1134,32 @@ public class ListPopupWindow {
     *
     *
     * @hide
     * @hide
     */
     */
    public static abstract class ForwardingListener implements View.OnTouchListener {
    public static abstract class ForwardingListener
            implements View.OnTouchListener, View.OnAttachStateChangeListener {
        /** Scaled touch slop, used for detecting movement outside bounds. */
        /** Scaled touch slop, used for detecting movement outside bounds. */
        private final float mScaledTouchSlop;
        private final float mScaledTouchSlop;


        /** Timeout before disallowing intercept on the source's parent. */
        private final int mTapTimeout;

        /** Source view from which events are forwarded. */
        private final View mSrc;

        /** Runnable used to prevent conflicts with scrolling parents. */
        private Runnable mDisallowIntercept;

        /** Whether this listener is currently forwarding touch events. */
        /** Whether this listener is currently forwarding touch events. */
        private boolean mForwarding;
        private boolean mForwarding;


        /** The id of the first pointer down in the current event stream. */
        /** The id of the first pointer down in the current event stream. */
        private int mActivePointerId;
        private int mActivePointerId;


        public ForwardingListener(Context context) {
        public ForwardingListener(View src) {
            mScaledTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
            mSrc = src;
            mScaledTouchSlop = ViewConfiguration.get(src.getContext()).getScaledTouchSlop();
            mTapTimeout = ViewConfiguration.getTapTimeout();

            src.addOnAttachStateChangeListener(this);
        }
        }


        /**
        /**
@@ -1164,15 +1179,29 @@ public class ListPopupWindow {
            final boolean wasForwarding = mForwarding;
            final boolean wasForwarding = mForwarding;
            final boolean forwarding;
            final boolean forwarding;
            if (wasForwarding) {
            if (wasForwarding) {
                forwarding = onTouchForwarded(v, event) || !onForwardingStopped();
                forwarding = onTouchForwarded(event) || !onForwardingStopped();
            } else {
            } else {
                forwarding = onTouchObserved(v, event) && onForwardingStarted();
                forwarding = onTouchObserved(event) && onForwardingStarted();
            }
            }


            mForwarding = forwarding;
            mForwarding = forwarding;
            return forwarding || wasForwarding;
            return forwarding || wasForwarding;
        }
        }


        @Override
        public void onViewAttachedToWindow(View v) {
        }

        @Override
        public void onViewDetachedFromWindow(View v) {
            mForwarding = false;
            mActivePointerId = MotionEvent.INVALID_POINTER_ID;

            if (mDisallowIntercept != null) {
                mSrc.removeCallbacks(mDisallowIntercept);
            }
        }

        /**
        /**
         * Called when forwarding would like to start.
         * Called when forwarding would like to start.
         * <p>
         * <p>
@@ -1182,7 +1211,7 @@ public class ListPopupWindow {
         *
         *
         * @return true to start forwarding, false otherwise
         * @return true to start forwarding, false otherwise
         */
         */
        public boolean onForwardingStarted() {
        protected boolean onForwardingStarted() {
            final ListPopupWindow popup = getPopup();
            final ListPopupWindow popup = getPopup();
            if (popup != null && !popup.isShowing()) {
            if (popup != null && !popup.isShowing()) {
                popup.show();
                popup.show();
@@ -1199,7 +1228,7 @@ public class ListPopupWindow {
         *
         *
         * @return true to stop forwarding, false otherwise
         * @return true to stop forwarding, false otherwise
         */
         */
        public boolean onForwardingStopped() {
        protected boolean onForwardingStopped() {
            final ListPopupWindow popup = getPopup();
            final ListPopupWindow popup = getPopup();
            if (popup != null && popup.isShowing()) {
            if (popup != null && popup.isShowing()) {
                popup.dismiss();
                popup.dismiss();
@@ -1210,30 +1239,46 @@ public class ListPopupWindow {
        /**
        /**
         * Observes motion events and determines when to start forwarding.
         * Observes motion events and determines when to start forwarding.
         *
         *
         * @param src view from which the event originated
         * @param srcEvent motion event in source view coordinates
         * @param srcEvent motion event in source view coordinates
         * @return true to start forwarding motion events, false otherwise
         * @return true to start forwarding motion events, false otherwise
         */
         */
        private boolean onTouchObserved(View src, MotionEvent srcEvent) {
        private boolean onTouchObserved(MotionEvent srcEvent) {
            final View src = mSrc;
            if (!src.isEnabled()) {
            if (!src.isEnabled()) {
                return false;
                return false;
            }
            }


            // The first pointer down is always the active pointer.
            final int actionMasked = srcEvent.getActionMasked();
            final int actionMasked = srcEvent.getActionMasked();
            if (actionMasked == MotionEvent.ACTION_DOWN) {
            switch (actionMasked) {
                case MotionEvent.ACTION_DOWN:
                    mActivePointerId = srcEvent.getPointerId(0);
                    mActivePointerId = srcEvent.getPointerId(0);
                    if (mDisallowIntercept == null) {
                        mDisallowIntercept = new DisallowIntercept();
                    }
                    }

                    src.postDelayed(mDisallowIntercept, mTapTimeout);
                    break;
                case MotionEvent.ACTION_MOVE:
                    final int activePointerIndex = srcEvent.findPointerIndex(mActivePointerId);
                    final int activePointerIndex = srcEvent.findPointerIndex(mActivePointerId);
                    if (activePointerIndex >= 0) {
                    if (activePointerIndex >= 0) {
                        final float x = srcEvent.getX(activePointerIndex);
                        final float x = srcEvent.getX(activePointerIndex);
                        final float y = srcEvent.getY(activePointerIndex);
                        final float y = srcEvent.getY(activePointerIndex);
                        if (!src.pointInView(x, y, mScaledTouchSlop)) {
                        if (!src.pointInView(x, y, mScaledTouchSlop)) {
                            // The pointer has moved outside of the view.
                            // The pointer has moved outside of the view.
                            if (mDisallowIntercept != null) {
                                src.removeCallbacks(mDisallowIntercept);
                            }
                            src.getParent().requestDisallowInterceptTouchEvent(true);
                            return true;
                            return true;
                        }
                        }
                    }
                    }
                    break;
                case MotionEvent.ACTION_CANCEL:
                case MotionEvent.ACTION_UP:
                    if (mDisallowIntercept != null) {
                        src.removeCallbacks(mDisallowIntercept);
                    }
                    break;
            }


            return false;
            return false;
        }
        }
@@ -1242,11 +1287,11 @@ public class ListPopupWindow {
         * Handled forwarded motion events and determines when to stop
         * Handled forwarded motion events and determines when to stop
         * forwarding.
         * forwarding.
         *
         *
         * @param src view from which the event originated
         * @param srcEvent motion event in source view coordinates
         * @param srcEvent motion event in source view coordinates
         * @return true to continue forwarding motion events, false to cancel
         * @return true to continue forwarding motion events, false to cancel
         */
         */
        private boolean onTouchForwarded(View src, MotionEvent srcEvent) {
        private boolean onTouchForwarded(MotionEvent srcEvent) {
            final View src = mSrc;
            final ListPopupWindow popup = getPopup();
            final ListPopupWindow popup = getPopup();
            if (popup == null || !popup.isShowing()) {
            if (popup == null || !popup.isShowing()) {
                return false;
                return false;
@@ -1267,6 +1312,14 @@ public class ListPopupWindow {
            dstEvent.recycle();
            dstEvent.recycle();
            return handled;
            return handled;
        }
        }

        private class DisallowIntercept implements Runnable {
            @Override
            public void run() {
                final ViewParent parent = mSrc.getParent();
                parent.requestDisallowInterceptTouchEvent(true);
            }
        }
    }
    }


    /**
    /**
+1 −1
Original line number Original line Diff line number Diff line
@@ -198,7 +198,7 @@ public class Spinner extends AbsSpinner implements OnClickListener {
            }
            }


            mPopup = popup;
            mPopup = popup;
            mForwardingListener = new ForwardingListener(context) {
            mForwardingListener = new ForwardingListener(this) {
                @Override
                @Override
                public ListPopupWindow getPopup() {
                public ListPopupWindow getPopup() {
                    return popup;
                    return popup;
+1 −1
Original line number Original line Diff line number Diff line
@@ -565,7 +565,7 @@ public class ActionMenuPresenter extends BaseMenuPresenter
            setVisibility(VISIBLE);
            setVisibility(VISIBLE);
            setEnabled(true);
            setEnabled(true);


            setOnTouchListener(new ForwardingListener(context) {
            setOnTouchListener(new ForwardingListener(this) {
                @Override
                @Override
                public ListPopupWindow getPopup() {
                public ListPopupWindow getPopup() {
                    if (mOverflowPopup == null) {
                    if (mOverflowPopup == null) {