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

Commit 8afa5159 authored by Romain Guy's avatar Romain Guy
Browse files

Send cancel event to recycled views instead of an up.

Bug #2309387

This was a problem in lists with list items that would cause notifyDatasetChanged()
interleaved with a series of up/down motion events. This is a pretty rare case
but it's worth fixing it to avoid getting views in a weird state.
parent b5e15690
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -1506,6 +1506,13 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
     */
    private static final int PREPRESSED             = 0x02000000;
    
    /**
     * Indicates whether the view is temporarily detached.
     *
     * @hide
     */
    static final int CANCEL_NEXT_UP_EVENT = 0x04000000;
    
    /**
     * Always allow a user to overscroll this view, provided it is a
     * view that can scroll.
@@ -3668,6 +3675,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
     */
    public void onStartTemporaryDetach() {
        removeUnsetPressCallback();
        mPrivateFlags |= CANCEL_NEXT_UP_EVENT;
    }

    /**
@@ -5913,6 +5921,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
     * @see #onAttachedToWindow()
     */
    protected void onDetachedFromWindow() {
        mPrivateFlags &= ~CANCEL_NEXT_UP_EVENT;
        removeUnsetPressCallback();
        removeLongPressCallback();
        destroyDrawingCache();
+12 −0
Original line number Diff line number Diff line
@@ -859,6 +859,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
                            final float xc = scrolledXFloat - child.mLeft;
                            final float yc = scrolledYFloat - child.mTop;
                            ev.setLocation(xc, yc);
                            child.mPrivateFlags &= ~CANCEL_NEXT_UP_EVENT;
                            if (child.dispatchTouchEvent(ev))  {
                                // Event handled, we have a target now.
                                mMotionTarget = child;
@@ -889,6 +890,10 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
            // We don't have a target, this means we're handling the
            // event as a regular view.
            ev.setLocation(xf, yf);
            if ((mPrivateFlags & CANCEL_NEXT_UP_EVENT) != 0) {
                ev.setAction(MotionEvent.ACTION_CANCEL);
                mPrivateFlags &= ~CANCEL_NEXT_UP_EVENT;
            }
            return super.dispatchTouchEvent(ev);
        }

@@ -897,6 +902,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
        if (!disallowIntercept && onInterceptTouchEvent(ev)) {
            final float xc = scrolledXFloat - (float) target.mLeft;
            final float yc = scrolledYFloat - (float) target.mTop;
            mPrivateFlags &= ~CANCEL_NEXT_UP_EVENT;
            ev.setAction(MotionEvent.ACTION_CANCEL);
            ev.setLocation(xc, yc);
            if (!target.dispatchTouchEvent(ev)) {
@@ -921,6 +927,12 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
        final float yc = scrolledYFloat - (float) target.mTop;
        ev.setLocation(xc, yc);

        if ((target.mPrivateFlags & CANCEL_NEXT_UP_EVENT) != 0) {
            ev.setAction(MotionEvent.ACTION_CANCEL);
            target.mPrivateFlags &= ~CANCEL_NEXT_UP_EVENT;
            mMotionTarget = null;
        }

        return target.dispatchTouchEvent(ev);
    }