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

Commit baa9a3f4 authored by Evan Rosky's avatar Evan Rosky Committed by Android (Google) Code Review
Browse files

Merge "More finishing-up of cluster implementation" into oc-dev

parents 0bbde28d bd10c52f
Loading
Loading
Loading
Loading
+40 −6
Original line number Original line Diff line number Diff line
@@ -54,7 +54,9 @@ public class FocusFinder {
    final Rect mOtherRect = new Rect();
    final Rect mOtherRect = new Rect();
    final Rect mBestCandidateRect = new Rect();
    final Rect mBestCandidateRect = new Rect();
    private final UserSpecifiedFocusComparator mUserSpecifiedFocusComparator =
    private final UserSpecifiedFocusComparator mUserSpecifiedFocusComparator =
            new UserSpecifiedFocusComparator();
            new UserSpecifiedFocusComparator((v) -> v.getNextFocusForwardId());
    private final UserSpecifiedFocusComparator mUserSpecifiedClusterComparator =
            new UserSpecifiedFocusComparator((v) -> v.getNextClusterForwardId());
    private final FocusComparator mFocusComparator = new FocusComparator();
    private final FocusComparator mFocusComparator = new FocusComparator();


    private final ArrayList<View> mTempList = new ArrayList<View>();
    private final ArrayList<View> mTempList = new ArrayList<View>();
@@ -150,6 +152,12 @@ public class FocusFinder {
            @Nullable View currentCluster,
            @Nullable View currentCluster,
            @View.FocusDirection int direction) {
            @View.FocusDirection int direction) {
        View next = null;
        View next = null;
        if (currentCluster != null) {
            next = findNextUserSpecifiedKeyboardNavigationCluster(root, currentCluster, direction);
            if (next != null) {
                return next;
            }
        }


        final ArrayList<View> clusters = mTempList;
        final ArrayList<View> clusters = mTempList;
        try {
        try {
@@ -165,6 +173,16 @@ public class FocusFinder {
        return next;
        return next;
    }
    }


    private View findNextUserSpecifiedKeyboardNavigationCluster(View root, View currentCluster,
            int direction) {
        View userSetNextCluster =
                currentCluster.findUserSetNextKeyboardNavigationCluster(root, direction);
        if (userSetNextCluster != null && userSetNextCluster.hasFocusable()) {
            return userSetNextCluster;
        }
        return null;
    }

    private View findNextUserSpecifiedFocus(ViewGroup root, View focused, int direction) {
    private View findNextUserSpecifiedFocus(ViewGroup root, View focused, int direction) {
        // check for user specified next focus
        // check for user specified next focus
        View userSetNextFocus = focused.findUserSetNextFocus(root, direction);
        View userSetNextFocus = focused.findUserSetNextFocus(root, direction);
@@ -238,6 +256,13 @@ public class FocusFinder {
            View currentCluster,
            View currentCluster,
            List<View> clusters,
            List<View> clusters,
            @View.FocusDirection int direction) {
            @View.FocusDirection int direction) {
        try {
            // Note: This sort is stable.
            mUserSpecifiedClusterComparator.setFocusables(clusters);
            Collections.sort(clusters, mUserSpecifiedClusterComparator);
        } finally {
            mUserSpecifiedClusterComparator.recycle();
        }
        final int count = clusters.size();
        final int count = clusters.size();


        switch (direction) {
        switch (direction) {
@@ -802,6 +827,15 @@ public class FocusFinder {
        private final SparseBooleanArray mIsConnectedTo = new SparseBooleanArray();
        private final SparseBooleanArray mIsConnectedTo = new SparseBooleanArray();
        private final ArrayMap<View, View> mHeadsOfChains = new ArrayMap<View, View>();
        private final ArrayMap<View, View> mHeadsOfChains = new ArrayMap<View, View>();
        private final ArrayMap<View, Integer> mOriginalOrdinal = new ArrayMap<>();
        private final ArrayMap<View, Integer> mOriginalOrdinal = new ArrayMap<>();
        private final NextIdGetter mNextIdGetter;

        public interface NextIdGetter {
            int get(View view);
        }

        UserSpecifiedFocusComparator(NextIdGetter nextIdGetter) {
            mNextIdGetter = nextIdGetter;
        }


        public void recycle() {
        public void recycle() {
            mFocusables.clear();
            mFocusables.clear();
@@ -810,14 +844,14 @@ public class FocusFinder {
            mOriginalOrdinal.clear();
            mOriginalOrdinal.clear();
        }
        }


        public void setFocusables(ArrayList<View> focusables) {
        public void setFocusables(List<View> focusables) {
            for (int i = focusables.size() - 1; i >= 0; i--) {
            for (int i = focusables.size() - 1; i >= 0; i--) {
                final View view = focusables.get(i);
                final View view = focusables.get(i);
                final int id = view.getId();
                final int id = view.getId();
                if (isValidId(id)) {
                if (isValidId(id)) {
                    mFocusables.put(id, view);
                    mFocusables.put(id, view);
                }
                }
                final int nextId = view.getNextFocusForwardId();
                final int nextId = mNextIdGetter.get(view);
                if (isValidId(nextId)) {
                if (isValidId(nextId)) {
                    mIsConnectedTo.put(nextId, true);
                    mIsConnectedTo.put(nextId, true);
                }
                }
@@ -825,7 +859,7 @@ public class FocusFinder {


            for (int i = focusables.size() - 1; i >= 0; i--) {
            for (int i = focusables.size() - 1; i >= 0; i--) {
                final View view = focusables.get(i);
                final View view = focusables.get(i);
                final int nextId = view.getNextFocusForwardId();
                final int nextId = mNextIdGetter.get(view);
                if (isValidId(nextId) && !mIsConnectedTo.get(view.getId())) {
                if (isValidId(nextId) && !mIsConnectedTo.get(view.getId())) {
                    setHeadOfChain(view);
                    setHeadOfChain(view);
                }
                }
@@ -838,7 +872,7 @@ public class FocusFinder {


        private void setHeadOfChain(View head) {
        private void setHeadOfChain(View head) {
            for (View view = head; view != null;
            for (View view = head; view != null;
                    view = mFocusables.get(view.getNextFocusForwardId())) {
                    view = mFocusables.get(mNextIdGetter.get(view))) {
                final View otherHead = mHeadsOfChains.get(view);
                final View otherHead = mHeadsOfChains.get(view);
                if (otherHead != null) {
                if (otherHead != null) {
                    if (otherHead == head) {
                    if (otherHead == head) {
@@ -866,7 +900,7 @@ public class FocusFinder {
                    return -1; // first is the head, it should be first
                    return -1; // first is the head, it should be first
                } else if (second == firstHead) {
                } else if (second == firstHead) {
                    return 1; // second is the head, it should be first
                    return 1; // second is the head, it should be first
                } else if (isValidId(first.getNextFocusForwardId())) {
                } else if (isValidId(mNextIdGetter.get(first))) {
                    return -1; // first is not the end of the chain
                    return -1; // first is not the end of the chain
                } else {
                } else {
                    return 1; // first is end of chain
                    return 1; // first is end of chain
+29 −1
Original line number Original line Diff line number Diff line
@@ -707,13 +707,16 @@ import java.util.function.Predicate;
 * @attr ref android.R.styleable#View_isScrollContainer
 * @attr ref android.R.styleable#View_isScrollContainer
 * @attr ref android.R.styleable#View_focusable
 * @attr ref android.R.styleable#View_focusable
 * @attr ref android.R.styleable#View_focusableInTouchMode
 * @attr ref android.R.styleable#View_focusableInTouchMode
 * @attr ref android.R.styleable#View_focusedByDefault
 * @attr ref android.R.styleable#View_hapticFeedbackEnabled
 * @attr ref android.R.styleable#View_hapticFeedbackEnabled
 * @attr ref android.R.styleable#View_keepScreenOn
 * @attr ref android.R.styleable#View_keepScreenOn
 * @attr ref android.R.styleable#View_keyboardNavigationCluster
 * @attr ref android.R.styleable#View_layerType
 * @attr ref android.R.styleable#View_layerType
 * @attr ref android.R.styleable#View_layoutDirection
 * @attr ref android.R.styleable#View_layoutDirection
 * @attr ref android.R.styleable#View_longClickable
 * @attr ref android.R.styleable#View_longClickable
 * @attr ref android.R.styleable#View_minHeight
 * @attr ref android.R.styleable#View_minHeight
 * @attr ref android.R.styleable#View_minWidth
 * @attr ref android.R.styleable#View_minWidth
 * @attr ref android.R.styleable#View_nextClusterForward
 * @attr ref android.R.styleable#View_nextFocusDown
 * @attr ref android.R.styleable#View_nextFocusDown
 * @attr ref android.R.styleable#View_nextFocusLeft
 * @attr ref android.R.styleable#View_nextFocusLeft
 * @attr ref android.R.styleable#View_nextFocusRight
 * @attr ref android.R.styleable#View_nextFocusRight
@@ -4076,7 +4079,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
    int mNextFocusForwardId = View.NO_ID;
    int mNextFocusForwardId = View.NO_ID;
    /**
    /**
     * User-specified next keyboard navigation cluster.
     * User-specified next keyboard navigation cluster in the {@link #FOCUS_FORWARD} direction.
     *
     * @see #findUserSetNextKeyboardNavigationCluster(View, int)
     */
     */
    int mNextClusterForwardId = View.NO_ID;
    int mNextClusterForwardId = View.NO_ID;
@@ -9968,6 +9973,29 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
        return null;
        return null;
    }
    }
    /**
     * If a user manually specified the next keyboard-navigation cluster for a particular direction,
     * use the root to look up the view.
     *
     * @param root the root view of the hierarchy containing this view
     * @param direction {@link #FOCUS_FORWARD} or {@link #FOCUS_BACKWARD}
     * @return the user-specified next cluster, or {@code null} if there is none
     */
    View findUserSetNextKeyboardNavigationCluster(View root, @FocusDirection int direction) {
        switch (direction) {
            case FOCUS_FORWARD:
                if (mNextClusterForwardId == View.NO_ID) return null;
                return findViewInsideOutShouldExist(root, mNextClusterForwardId);
            case FOCUS_BACKWARD: {
                if (mID == View.NO_ID) return null;
                final int id = mID;
                return root.findViewByPredicateInsideOut(this,
                        (Predicate<View>) t -> t.mNextClusterForwardId == id);
            }
        }
        return null;
    }
    private View findViewInsideOutShouldExist(View root, int id) {
    private View findViewInsideOutShouldExist(View root, int id) {
        if (mMatchIdPredicate == null) {
        if (mMatchIdPredicate == null) {
            mMatchIdPredicate = new MatchIdPredicate();
            mMatchIdPredicate = new MatchIdPredicate();
+9 −6
Original line number Original line Diff line number Diff line
@@ -1258,15 +1258,18 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
            return;
            return;
        }
        }


        final int count = mChildrenCount;
        int count = 0;
        final View[] children = mChildren;
        final View[] visibleChildren = new View[mChildrenCount];

        for (int i = 0; i < mChildrenCount; ++i) {
        for (int i = 0; i < count; i++) {
            final View child = mChildren[i];
            final View child = children[i];
            if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE) {
            if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE) {
                child.addKeyboardNavigationClusters(views, direction);
                visibleChildren[count++] = child;
            }
            }
        }
        }
        Arrays.sort(visibleChildren, 0, count, FocusFinder.getFocusComparator(this, false));
        for (int i = 0; i < count; ++i) {
            visibleChildren[i].addKeyboardNavigationClusters(views, direction);
        }
    }
    }


    /**
    /**
+2 −0
Original line number Original line Diff line number Diff line
@@ -4660,6 +4660,7 @@ public final class ViewRootImpl implements ViewParent,
            if (cluster != null && cluster.isRootNamespace()) {
            if (cluster != null && cluster.isRootNamespace()) {
                // the default cluster. Try to find a non-clustered view to focus.
                // the default cluster. Try to find a non-clustered view to focus.
                if (cluster.restoreFocusNotInCluster()) {
                if (cluster.restoreFocusNotInCluster()) {
                    playSoundEffect(SoundEffectConstants.getContantForFocusDirection(direction));
                    return true;
                    return true;
                }
                }
                // otherwise skip to next actual cluster
                // otherwise skip to next actual cluster
@@ -4667,6 +4668,7 @@ public final class ViewRootImpl implements ViewParent,
            }
            }


            if (cluster != null && cluster.restoreFocusInCluster(realDirection)) {
            if (cluster != null && cluster.restoreFocusInCluster(realDirection)) {
                playSoundEffect(SoundEffectConstants.getContantForFocusDirection(direction));
                return true;
                return true;
            }
            }