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

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

Merge "Separate cluster-focus and default-focus."

parents c1c1c23b 53fcf11c
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -44754,7 +44754,7 @@ package android.view {
    method public final void requestUnbufferedDispatch(android.view.MotionEvent);
    method public static int resolveSize(int, int);
    method public static int resolveSizeAndState(int, int, int);
    method public boolean restoreDefaultFocus(int);
    method public boolean restoreDefaultFocus();
    method public void restoreHierarchyState(android.util.SparseArray<android.os.Parcelable>);
    method public void saveHierarchyState(android.util.SparseArray<android.os.Parcelable>);
    method public void scheduleDrawable(android.graphics.drawable.Drawable, java.lang.Runnable, long);
+1 −1
Original line number Diff line number Diff line
@@ -48170,7 +48170,7 @@ package android.view {
    method public final void requestUnbufferedDispatch(android.view.MotionEvent);
    method public static int resolveSize(int, int);
    method public static int resolveSizeAndState(int, int, int);
    method public boolean restoreDefaultFocus(int);
    method public boolean restoreDefaultFocus();
    method public void restoreHierarchyState(android.util.SparseArray<android.os.Parcelable>);
    method public void saveHierarchyState(android.util.SparseArray<android.os.Parcelable>);
    method public void scheduleDrawable(android.graphics.drawable.Drawable, java.lang.Runnable, long);
+1 −1
Original line number Diff line number Diff line
@@ -45061,7 +45061,7 @@ package android.view {
    method public final void requestUnbufferedDispatch(android.view.MotionEvent);
    method public static int resolveSize(int, int);
    method public static int resolveSizeAndState(int, int, int);
    method public boolean restoreDefaultFocus(int);
    method public boolean restoreDefaultFocus();
    method public void restoreHierarchyState(android.util.SparseArray<android.os.Parcelable>);
    method public void saveHierarchyState(android.util.SparseArray<android.os.Parcelable>);
    method public void scheduleDrawable(android.graphics.drawable.Drawable, java.lang.Runnable, long);
+31 −8
Original line number Diff line number Diff line
@@ -6125,9 +6125,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
            if (mParent != null) {
                mParent.requestChildFocus(this, this);
                if (mParent instanceof ViewGroup) {
                    ((ViewGroup) mParent).setDefaultFocus(this);
                }
                setFocusedInCluster();
            }
            if (mAttachInfo != null) {
@@ -9244,6 +9242,19 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
        }
    }
    /**
     * Sets this View as the one which receives focus the next time cluster navigation jumps
     * to the cluster containing this View. This does NOT change focus even if the cluster
     * containing this view is current.
     *
     * @hide
     */
    public void setFocusedInCluster() {
        if (mParent instanceof ViewGroup) {
            ((ViewGroup) mParent).setFocusInCluster(this);
        }
    }
    /**
     * Returns whether this View should receive focus when the focus is restored for the view
     * hierarchy containing this view.
@@ -9290,7 +9301,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
            if (isFocusedByDefault) {
                ((ViewGroup) mParent).setDefaultFocus(this);
            } else {
                ((ViewGroup) mParent).cleanDefaultFocus(this);
                ((ViewGroup) mParent).clearDefaultFocus(this);
            }
        }
    }
@@ -9669,16 +9680,28 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
        return requestFocus(View.FOCUS_DOWN);
    }
    /**
     * Public for testing. This will request focus for whichever View was last focused within this
     * cluster before a focus-jump out of it.
     *
     * @hide
     */
    public boolean restoreFocusInCluster(@FocusRealDirection int direction) {
        // Prioritize focusableByDefault over algorithmic focus selection.
        if (restoreDefaultFocus()) {
            return true;
        }
        return requestFocus(direction);
    }
    /**
     * Gives focus to the default-focus view in the view hierarchy that has this view as a root.
     * If the default-focus view cannot be found, falls back to calling {@link #requestFocus(int)}.
     * Nested keyboard navigation clusters are excluded from the hierarchy.
     *
     * @param direction The direction of the focus
     * @return Whether this view or one of its descendants actually took focus
     */
    public boolean restoreDefaultFocus(@FocusDirection int direction) {
        return requestFocus(direction);
    public boolean restoreDefaultFocus() {
        return requestFocus(View.FOCUS_DOWN);
    }
    /**
+98 −25
Original line number Diff line number Diff line
@@ -141,6 +141,8 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
    // The view contained within this ViewGroup (excluding nested keyboard navigation clusters)
    // that is or contains a default-focus view.
    private View mDefaultFocus;
    // The last child of this ViewGroup which held focus within the current cluster
    private View mFocusedInCluster;

    /**
     * A Transformation used when drawing children, to
@@ -724,7 +726,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
        if (mFocused != null) {
            mFocused.unFocus(this);
            mFocused = null;
            mDefaultFocus = null;
            mFocusedInCluster = null;
        }
        super.handleFocusGainInternal(direction, previouslyFocusedRect);
    }
@@ -754,14 +756,9 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
        }
    }

    /**
     * Sets the specified child view as the default focus for this view and all its ancestors.
     * If the view is inside a keyboard navigation cluster, stops at the root of the cluster since
     * the cluster forms a separate keyboard navigation hierarchy from the default focus point of
     * view.
     */
    void setDefaultFocus(View child) {
        if (child.isKeyboardNavigationCluster()) {
        // Stop at any higher view which is explicitly focused-by-default
        if (mDefaultFocus != null && mDefaultFocus.isFocusedByDefault()) {
            return;
        }

@@ -773,21 +770,33 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
    }

    /**
     * Destroys the default focus chain.
     * Clears the default-focus chain from {@param child} up to the first parent which has another
     * default-focusable branch below it or until there is no default-focus chain.
     *
     * @param child
     */
    void cleanDefaultFocus(View child) {
        if (mDefaultFocus != child) {
    void clearDefaultFocus(View child) {
        // Stop at any higher view which is explicitly focused-by-default
        if (mDefaultFocus != child && mDefaultFocus != null
                && mDefaultFocus.isFocusedByDefault()) {
            return;
        }

        if (child.isKeyboardNavigationCluster()) {
        mDefaultFocus = null;

        // Search child siblings for default focusables.
        for (int i = 0; i < mChildrenCount; ++i) {
            View sibling = mChildren[i];
            if (sibling.isFocusedByDefault()) {
                mDefaultFocus = sibling;
                return;
            } else if (mDefaultFocus == null && sibling.hasDefaultFocus()) {
                mDefaultFocus = sibling;
            }
        }

        mDefaultFocus = null;

        if (mParent instanceof ViewGroup) {
            ((ViewGroup) mParent).cleanDefaultFocus(this);
            ((ViewGroup) mParent).clearDefaultFocus(this);
        }
    }

@@ -796,6 +805,35 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
        return mDefaultFocus != null || super.hasDefaultFocus();
    }

    void setFocusInCluster(View child) {
        // Stop at the root of the cluster
        if (child.isKeyboardNavigationCluster()) {
            return;
        }

        mFocusedInCluster = child;

        if (mParent instanceof ViewGroup) {
            ((ViewGroup) mParent).setFocusInCluster(this);
        }
    }

    void clearFocusInCluster(View child) {
        if (mFocusedInCluster != child) {
            return;
        }

        if (child.isKeyboardNavigationCluster()) {
            return;
        }

        mFocusedInCluster = null;

        if (mParent instanceof ViewGroup) {
            ((ViewGroup) mParent).clearFocusInCluster(this);
        }
    }

    @Override
    public void focusableViewAvailable(View v) {
        if (mParent != null
@@ -3115,14 +3153,28 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
    }

    @Override
    public boolean restoreDefaultFocus(@FocusDirection int direction) {
        if (mDefaultFocus != null && !mDefaultFocus.isKeyboardNavigationCluster()
    public boolean restoreDefaultFocus() {
        if (mDefaultFocus != null
                && getDescendantFocusability() != FOCUS_BLOCK_DESCENDANTS
                && (mDefaultFocus.mViewFlags & VISIBILITY_MASK) == VISIBLE
                && mDefaultFocus.restoreDefaultFocus(direction)) {
                && mDefaultFocus.restoreDefaultFocus()) {
            return true;
        }
        return super.restoreDefaultFocus();
    }

    /**
     * @hide
     */
    @Override
    public boolean restoreFocusInCluster(@FocusRealDirection int direction) {
        if (mFocusedInCluster != null && !mFocusedInCluster.isKeyboardNavigationCluster()
                && getDescendantFocusability() != FOCUS_BLOCK_DESCENDANTS
                && (mFocusedInCluster.mViewFlags & VISIBILITY_MASK) == VISIBLE
                && mFocusedInCluster.restoreFocusInCluster(direction)) {
            return true;
        }
        return super.restoreDefaultFocus(direction);
        return super.restoreFocusInCluster(direction);
    }

    /**
@@ -5004,8 +5056,8 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
            view.unFocus(null);
            clearChildFocus = true;
        }
        if (view == mDefaultFocus) {
            mDefaultFocus = null;
        if (view == mFocusedInCluster) {
            clearFocusInCluster(view);
        }

        view.clearAccessibilityFocus();
@@ -5028,6 +5080,9 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager

        removeFromArray(index);

        if (view == mDefaultFocus) {
            clearDefaultFocus(view);
        }
        if (clearChildFocus) {
            clearChildFocus(view);
            if (!rootViewRequestFocus()) {
@@ -5103,6 +5158,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
        final View focused = mFocused;
        final boolean detach = mAttachInfo != null;
        boolean clearChildFocus = false;
        View clearDefaultFocus = null;

        final View[] children = mChildren;

@@ -5118,7 +5174,10 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
                clearChildFocus = true;
            }
            if (view == mDefaultFocus) {
                mDefaultFocus = null;
                clearDefaultFocus = view;
            }
            if (view == mFocusedInCluster) {
                clearFocusInCluster(view);
            }

            view.clearAccessibilityFocus();
@@ -5144,6 +5203,9 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager

        removeFromArray(start, count);

        if (clearDefaultFocus != null) {
            clearDefaultFocus(clearDefaultFocus);
        }
        if (clearChildFocus) {
            clearChildFocus(focused);
            if (!rootViewRequestFocus()) {
@@ -5193,7 +5255,6 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
        boolean clearChildFocus = false;

        needGlobalAttributesUpdate(false);
        mDefaultFocus = null;

        for (int i = count - 1; i >= 0; i--) {
            final View view = children[i];
@@ -5229,6 +5290,9 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
            children[i] = null;
        }

        if (mDefaultFocus != null) {
            clearDefaultFocus(mDefaultFocus);
        }
        if (clearChildFocus) {
            clearChildFocus(focused);
            if (!rootViewRequestFocus()) {
@@ -5266,7 +5330,10 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
            child.clearFocus();
        }
        if (child == mDefaultFocus) {
            mDefaultFocus = null;
            clearDefaultFocus(child);
        }
        if (child == mFocusedInCluster) {
            clearFocusInCluster(child);
        }

        child.clearAccessibilityFocus();
@@ -6251,6 +6318,12 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
            Log.d(VIEW_LOG_TAG, output);
            mDefaultFocus.debug(depth + 1);
        }
        if (mFocusedInCluster != null) {
            output = debugIndent(depth);
            output += "mFocusedInCluster";
            Log.d(VIEW_LOG_TAG, output);
            mFocusedInCluster.debug(depth + 1);
        }
        if (mChildrenCount != 0) {
            output = debugIndent(depth);
            output += "{";
Loading