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

Commit a440b002 authored by Romain Guy's avatar Romain Guy
Browse files

Prevents ListView items children to modify properties of other children.

Bug #2464502

This fix introduce a new dispatch mechanism to tell views when they are temporary
detached/reattached from/to a ListView. This is very important to remove pending
callbacks or cleanup temporary states.

This change also modifies TextView which was relying on that callback in a very
particular case: a focused EditText in a ListView. The modified code acts only
when in that case, not if onStart/FinishTemporaryDetach() is called via
dispatch*() (== recycled views in ListView.)
parent 618c8f1e
Loading
Loading
Loading
Loading
+29 −11
Original line number Diff line number Diff line
@@ -3650,14 +3650,27 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
    }

    /**
     * This is called when a container is going to temporarily detach a child
     * that currently has focus, with
     * @hide
     */
    public void dispatchStartTemporaryDetach() {
        onStartTemporaryDetach();
    }

    /**
     * This is called when a container is going to temporarily detach a child, with
     * {@link ViewGroup#detachViewFromParent(View) ViewGroup.detachViewFromParent}.
     * It will either be followed by {@link #onFinishTemporaryDetach()} or
     * {@link #onDetachedFromWindow()} when the container is done.  Generally
     * this is currently only done ListView for a view with focus.
     * {@link #onDetachedFromWindow()} when the container is done.
     */
    public void onStartTemporaryDetach() {
        removeUnsetPressCallback();
    }

    /**
     * @hide
     */
    public void dispatchFinishTemporaryDetach() {
        onFinishTemporaryDetach();
    }

    /**
@@ -4361,6 +4374,16 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
        }
    }
    
    /**
     * Remove the prepress detection timer.
     */
    private void removeUnsetPressCallback() {
        if ((mPrivateFlags & PRESSED) != 0 && mUnsetPressedState != null) {
            setPressed(false);
            removeCallbacks(mUnsetPressedState);
        }
    }

    /**
     * Remove the tap detection timer.
     */
@@ -5886,6 +5909,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
     * @see #onAttachedToWindow()
     */
    protected void onDetachedFromWindow() {
        removeUnsetPressCallback();
        removeLongPressCallback();
        destroyDrawingCache();
    }
@@ -9181,12 +9205,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
         */
        boolean mRecomputeGlobalAttributes;

        /**
         * Set to true when attributes (like mKeepScreenOn) need to be
         * recomputed.
         */
        boolean mAttributesChanged;

        /**
         * Set during a traveral if any views want to keep the screen on.
         */
+26 −0
Original line number Diff line number Diff line
@@ -1066,6 +1066,32 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
        return false;
    }
    
    /**
     * {@inheritDoc}
     */
    @Override
    public void dispatchStartTemporaryDetach() {
        super.dispatchStartTemporaryDetach();
        final int count = mChildrenCount;
        final View[] children = mChildren;
        for (int i = 0; i < count; i++) {
            children[i].dispatchStartTemporaryDetach();
        }
    }
    
    /**
     * {@inheritDoc}
     */
    @Override
    public void dispatchFinishTemporaryDetach() {
        super.dispatchFinishTemporaryDetach();
        final int count = mChildrenCount;
        final View[] children = mChildren;
        for (int i = 0; i < count; i++) {
            children[i].dispatchFinishTemporaryDetach();
        }
    }

    /**
     * {@inheritDoc}
     */
+6 −2
Original line number Diff line number Diff line
@@ -1315,6 +1315,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
                }
            } else {
                isScrap[0] = true;
                child.dispatchFinishTemporaryDetach();
            }
        } else {
            child = mAdapter.getView(position, null, this);
@@ -4145,8 +4146,10 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
            }

            if (mViewTypeCount == 1) {
                scrap.dispatchStartTemporaryDetach();
                mCurrentScrap.add(scrap);
            } else {
                scrap.dispatchStartTemporaryDetach();
                mScrapViews[viewType].add(scrap);
            }

@@ -4165,7 +4168,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te

            ArrayList<View> scrapViews = mCurrentScrap;
            final int count = activeViews.length;
            for (int i = 0; i < count; ++i) {
            for (int i = count - 1; i >= 0; i--) {
                final View victim = activeViews[i];
                if (victim != null) {
                    int whichScrap = ((AbsListView.LayoutParams) victim.getLayoutParams()).viewType;
@@ -4181,6 +4184,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
                    if (multipleScraps) {
                        scrapViews = mScrapViews[whichScrap];
                    }
                    victim.dispatchStartTemporaryDetach();
                    scrapViews.add(victim);

                    if (hasListener) {
+0 −1
Original line number Diff line number Diff line
@@ -1485,7 +1485,6 @@ public class ListView extends AbsListView {
            }

            // Clear out old views
            //removeAllViewsInLayout();
            detachAllViewsFromParent();

            switch (mLayoutMode) {
+16 −2
Original line number Diff line number Diff line
@@ -198,6 +198,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
    private boolean mFreezesText;
    private boolean mFrozenWithFocus;
    private boolean mTemporaryDetach;
    private boolean mDispatchTemporaryDetach;

    private boolean mEatTouchRelease = false;
    private boolean mScrolled = false;
@@ -6371,14 +6372,27 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
        mBlink.postAtTime(mBlink, mShowCursor + BLINK);
    }

    @Override
    public void dispatchFinishTemporaryDetach() {
        mDispatchTemporaryDetach = true;
        super.dispatchFinishTemporaryDetach();
        mDispatchTemporaryDetach = false;
    }

    @Override
    public void onStartTemporaryDetach() {
        mTemporaryDetach = true;
        super.onStartTemporaryDetach();
        // Only track when onStartTemporaryDetach() is called directly,
        // usually because this instance is an editable field in a list
        if (!mDispatchTemporaryDetach) mTemporaryDetach = true;
    }
    
    @Override
    public void onFinishTemporaryDetach() {
        mTemporaryDetach = false;
        super.onFinishTemporaryDetach();
        // Only track when onStartTemporaryDetach() is called directly,
        // usually because this instance is an editable field in a list
        if (!mDispatchTemporaryDetach) mTemporaryDetach = false;
    }
    
    @Override