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

Commit b891a58e authored by Evan Rosky's avatar Evan Rosky
Browse files

Revert "Don't allow 0-sized views to be focused."

This reverts commit f6b2c6ec.

Reason for revert: TextView interracts poorly

Change-Id: I57496aaf946972791c9a2a1ecc64151f1111f11e
parent f6b2c6ec
Loading
Loading
Loading
Loading
+19 −103
Original line number Original line Diff line number Diff line
@@ -4163,11 +4163,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
     */
     */
    private static boolean sUseDefaultFocusHighlight;
    private static boolean sUseDefaultFocusHighlight;
    /**
     * True if zero-sized views can be focused.
     */
    private static boolean sCanFocusZeroSized;
    private String mTransitionName;
    private String mTransitionName;
    static class TintInfo {
    static class TintInfo {
@@ -4748,8 +4743,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
            sUseDefaultFocusHighlight = context.getResources().getBoolean(
            sUseDefaultFocusHighlight = context.getResources().getBoolean(
                    com.android.internal.R.bool.config_useDefaultFocusHighlight);
                    com.android.internal.R.bool.config_useDefaultFocusHighlight);
            sCanFocusZeroSized = targetSdkVersion < Build.VERSION_CODES.P;
            sCompatibilityDone = true;
            sCompatibilityDone = true;
        }
        }
    }
    }
@@ -6957,7 +6950,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
    void clearFocusInternal(View focused, boolean propagate, boolean refocus) {
    void clearFocusInternal(View focused, boolean propagate, boolean refocus) {
        if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
        if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
            mPrivateFlags &= ~PFLAG_FOCUSED;
            mPrivateFlags &= ~PFLAG_FOCUSED;
            clearParentsWantFocus();
            if (propagate && mParent != null) {
            if (propagate && mParent != null) {
                mParent.clearChildFocus(this);
                mParent.clearChildFocus(this);
@@ -10939,9 +10931,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
     * descendants.
     * descendants.
     *
     *
     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
     * false), or if it can't be focused due to other conditions (not focusable in touch mode
     * false), or if it is focusable and it is not focusable in touch mode
     * ({@link #isFocusableInTouchMode}) while the device is in touch mode, not visible, not
     * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
     * enabled, or has no size).
     *
     *
     * See also {@link #focusSearch(int)}, which is what you call to say that you
     * See also {@link #focusSearch(int)}, which is what you call to say that you
     * have focus, and you want your parent to look for the next one.
     * have focus, and you want your parent to look for the next one.
@@ -10979,17 +10970,17 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
     */
     */
    @TestApi
    @TestApi
    public boolean restoreFocusNotInCluster() {
    public boolean restoreFocusNotInCluster() {
        return requestFocus();
        return requestFocus(View.FOCUS_DOWN);
    }
    }
    /**
    /**
     * Gives focus to the default-focus view in the view hierarchy that has this view as a root.
     * 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()}.
     * If the default-focus view cannot be found, falls back to calling {@link #requestFocus(int)}.
     *
     *
     * @return Whether this view or one of its descendants actually took focus
     * @return Whether this view or one of its descendants actually took focus
     */
     */
    public boolean restoreDefaultFocus() {
    public boolean restoreDefaultFocus() {
        return requestFocus();
        return requestFocus(View.FOCUS_DOWN);
    }
    }
    /**
    /**
@@ -11048,7 +11039,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
    private boolean requestFocusNoSearch(int direction, Rect previouslyFocusedRect) {
    private boolean requestFocusNoSearch(int direction, Rect previouslyFocusedRect) {
        // need to be focusable
        // need to be focusable
        if (!canTakeFocus()) {
        if ((mViewFlags & FOCUSABLE) != FOCUSABLE
                || (mViewFlags & VISIBILITY_MASK) != VISIBLE
                || (mViewFlags & ENABLED_MASK) != ENABLED) {
            return false;
            return false;
        }
        }
@@ -11063,21 +11056,10 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
            return false;
            return false;
        }
        }
        if (!isLaidOut()) {
            mPrivateFlags |= PFLAG_WANTS_FOCUS;
        }
        handleFocusGainInternal(direction, previouslyFocusedRect);
        handleFocusGainInternal(direction, previouslyFocusedRect);
        return true;
        return true;
    }
    }
    void clearParentsWantFocus() {
        if (mParent instanceof View) {
            ((View) mParent).mPrivateFlags &= ~PFLAG_WANTS_FOCUS;
            ((View) mParent).clearParentsWantFocus();
        }
    }
    /**
    /**
     * Call this to try to give focus to a specific view or to one of its descendants. This is a
     * Call this to try to give focus to a specific view or to one of its descendants. This is a
     * special variant of {@link #requestFocus() } that will allow views that are not focusable in
     * special variant of {@link #requestFocus() } that will allow views that are not focusable in
@@ -13449,13 +13431,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
        mAttachInfo.mUnbufferedDispatchRequested = true;
        mAttachInfo.mUnbufferedDispatchRequested = true;
    }
    }
    private boolean canTakeFocus() {
        return ((mViewFlags & VISIBILITY_MASK) == VISIBLE)
                && ((mViewFlags & FOCUSABLE) == FOCUSABLE)
                && ((mViewFlags & ENABLED_MASK) == ENABLED)
                && (sCanFocusZeroSized || !isLaidOut() || (mBottom > mTop) && (mRight > mLeft));
    }
    /**
    /**
     * Set flags controlling behavior of this view.
     * Set flags controlling behavior of this view.
     *
     *
@@ -13475,7 +13450,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
            return;
            return;
        }
        }
        int privateFlags = mPrivateFlags;
        int privateFlags = mPrivateFlags;
        boolean shouldNotifyFocusableAvailable = false;
        // If focusable is auto, update the FOCUSABLE bit.
        // If focusable is auto, update the FOCUSABLE bit.
        int focusableChangedByAuto = 0;
        int focusableChangedByAuto = 0;
@@ -13514,7 +13488,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
                            || focusableChangedByAuto == 0
                            || focusableChangedByAuto == 0
                            || viewRootImpl == null
                            || viewRootImpl == null
                            || viewRootImpl.mThread == Thread.currentThread()) {
                            || viewRootImpl.mThread == Thread.currentThread()) {
                        shouldNotifyFocusableAvailable = true;
                        mParent.focusableViewAvailable(this);
                    }
                    }
                }
                }
            }
            }
@@ -13537,7 +13511,10 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
                // about in case nothing has focus.  even if this specific view
                // about in case nothing has focus.  even if this specific view
                // isn't focusable, it may contain something that is, so let
                // isn't focusable, it may contain something that is, so let
                // the root view try to give this focus if nothing else does.
                // the root view try to give this focus if nothing else does.
                shouldNotifyFocusableAvailable = true;
                if ((mParent != null) && ((mViewFlags & ENABLED_MASK) == ENABLED)
                        && (mBottom > mTop) && (mRight > mLeft)) {
                    mParent.focusableViewAvailable(this);
                }
            }
            }
        }
        }
@@ -13546,15 +13523,14 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
                // a view becoming enabled should notify the parent as long as the view is also
                // a view becoming enabled should notify the parent as long as the view is also
                // visible and the parent wasn't already notified by becoming visible during this
                // visible and the parent wasn't already notified by becoming visible during this
                // setFlags invocation.
                // setFlags invocation.
                shouldNotifyFocusableAvailable = true;
                if ((mViewFlags & VISIBILITY_MASK) == VISIBLE
            } else {
                        && ((changed & VISIBILITY_MASK) == 0)) {
                if (hasFocus()) clearFocus();
                    if ((mParent != null) && (mViewFlags & ENABLED_MASK) == ENABLED) {
                        mParent.focusableViewAvailable(this);
                    }
                    }
                }
                }
            } else {
        if (shouldNotifyFocusableAvailable) {
                if (hasFocus()) clearFocus();
            if (mParent != null && canTakeFocus()) {
                mParent.focusableViewAvailable(this);
            }
            }
        }
        }
@@ -20047,58 +20023,15 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
            }
            }
        }
        }
        final boolean wasLaidOut = isLaidOut();
        mPrivateFlags &= ~PFLAG_FORCE_LAYOUT;
        mPrivateFlags &= ~PFLAG_FORCE_LAYOUT;
        mPrivateFlags3 |= PFLAG3_IS_LAID_OUT;
        mPrivateFlags3 |= PFLAG3_IS_LAID_OUT;
        if (!wasLaidOut && isFocused()) {
            mPrivateFlags &= ~PFLAG_WANTS_FOCUS;
            if (canTakeFocus()) {
                // We have a robust focus, so parents should no longer be wanting focus.
                clearParentsWantFocus();
            } else if (!getViewRootImpl().isInLayout()) {
                // This is a weird case. Most-likely the user, rather than ViewRootImpl, called
                // layout. In this case, there's no guarantee that parent layouts will be evaluated
                // and thus the safest action is to clear focus here.
                clearFocusInternal(null, /* propagate */ true, /* refocus */ false);
                clearParentsWantFocus();
            } else if (!hasParentWantsFocus()) {
                // original requestFocus was likely on this view directly, so just clear focus
                clearFocusInternal(null, /* propagate */ true, /* refocus */ false);
            }
            // otherwise, we let parents handle re-assigning focus during their layout passes.
        } else if ((mPrivateFlags & PFLAG_WANTS_FOCUS) != 0) {
            mPrivateFlags &= ~PFLAG_WANTS_FOCUS;
            View focused = findFocus();
            if (focused != null) {
                // Try to restore focus as close as possible to our starting focus.
                if (!restoreDefaultFocus() && !hasParentWantsFocus()) {
                    // Give up and clear focus once we've reached the top-most parent which wants
                    // focus.
                    focused.clearFocusInternal(null, /* propagate */ true, /* refocus */ false);
                }
            }
        }
        if ((mPrivateFlags3 & PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT) != 0) {
        if ((mPrivateFlags3 & PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT) != 0) {
            mPrivateFlags3 &= ~PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT;
            mPrivateFlags3 &= ~PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT;
            notifyEnterOrExitForAutoFillIfNeeded(true);
            notifyEnterOrExitForAutoFillIfNeeded(true);
        }
        }
    }
    }
    private boolean hasParentWantsFocus() {
        ViewParent parent = mParent;
        while (parent instanceof ViewGroup) {
            ViewGroup pv = (ViewGroup) parent;
            if ((pv.mPrivateFlags & PFLAG_WANTS_FOCUS) != 0) {
                return true;
            }
            parent = pv.mParent;
        }
        return false;
    }
    /**
    /**
     * Called from layout when this view should
     * Called from layout when this view should
     * assign a size and position to each of its children.
     * assign a size and position to each of its children.
@@ -20205,23 +20138,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
            mOverlay.getOverlayView().setRight(newWidth);
            mOverlay.getOverlayView().setRight(newWidth);
            mOverlay.getOverlayView().setBottom(newHeight);
            mOverlay.getOverlayView().setBottom(newHeight);
        }
        }
        // If this isn't laid out yet, focus assignment will be handled during the "deferment/
        // backtracking" of requestFocus during layout, so don't touch focus here.
        if (!sCanFocusZeroSized && isLaidOut()) {
            if (newWidth <= 0 || newHeight <= 0) {
                if (hasFocus()) {
                    clearFocus();
                    if (mParent instanceof ViewGroup) {
                        ((ViewGroup) mParent).clearFocusedInCluster();
                    }
                }
                clearAccessibilityFocus();
            } else if (oldWidth <= 0 || oldHeight <= 0) {
                if (mParent != null && canTakeFocus()) {
                    mParent.focusableViewAvailable(this);
                }
            }
        }
        rebuildOutline();
        rebuildOutline();
    }
    }
+3 −12
Original line number Original line Diff line number Diff line
@@ -3215,31 +3215,22 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
        }
        }
        int descendantFocusability = getDescendantFocusability();
        int descendantFocusability = getDescendantFocusability();


        boolean result;
        switch (descendantFocusability) {
        switch (descendantFocusability) {
            case FOCUS_BLOCK_DESCENDANTS:
            case FOCUS_BLOCK_DESCENDANTS:
                result = super.requestFocus(direction, previouslyFocusedRect);
                return super.requestFocus(direction, previouslyFocusedRect);
                break;
            case FOCUS_BEFORE_DESCENDANTS: {
            case FOCUS_BEFORE_DESCENDANTS: {
                final boolean took = super.requestFocus(direction, previouslyFocusedRect);
                final boolean took = super.requestFocus(direction, previouslyFocusedRect);
                result = took ? took : onRequestFocusInDescendants(direction,
                return took ? took : onRequestFocusInDescendants(direction, previouslyFocusedRect);
                        previouslyFocusedRect);
                break;
            }
            }
            case FOCUS_AFTER_DESCENDANTS: {
            case FOCUS_AFTER_DESCENDANTS: {
                final boolean took = onRequestFocusInDescendants(direction, previouslyFocusedRect);
                final boolean took = onRequestFocusInDescendants(direction, previouslyFocusedRect);
                result = took ? took : super.requestFocus(direction, previouslyFocusedRect);
                return took ? took : super.requestFocus(direction, previouslyFocusedRect);
                break;
            }
            }
            default:
            default:
                throw new IllegalStateException("descendant focusability must be "
                throw new IllegalStateException("descendant focusability must be "
                        + "one of FOCUS_BEFORE_DESCENDANTS, FOCUS_AFTER_DESCENDANTS, FOCUS_BLOCK_DESCENDANTS "
                        + "one of FOCUS_BEFORE_DESCENDANTS, FOCUS_AFTER_DESCENDANTS, FOCUS_BLOCK_DESCENDANTS "
                        + "but is " + descendantFocusability);
                        + "but is " + descendantFocusability);
        }
        }
        if (result && !isLaidOut() && ((mPrivateFlags & PFLAG_WANTS_FOCUS) == 0)) {
            mPrivateFlags |= PFLAG_WANTS_FOCUS;
        }
        return result;
    }
    }


    /**
    /**