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

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

Enable new initial-focus behavior for P

This means that, by default, nothing gets initial focus
in touch-mode.

In order to have something focused in touch mode at
activity start, an app must explicitly provide a
<requestFocus /> tag. Since this tag uses the "default"
focus mechanism, it can be placed in a parent and focus
will go to whatever view is the default focusable in
that hierarchy.

This takes effect for targetApi >= P

Bug: 34520588
Test: Added CTS tests in View_InitialFocusTest
Change-Id: I74839bb86079558eaa5c96de52220a7d2c47d901
parent 8e18b621
Loading
Loading
Loading
Loading
+11 −3
Original line number Diff line number Diff line
@@ -4193,6 +4193,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
     */
    private static boolean sCanFocusZeroSized;
    /**
     * Always assign focus if a focusable View is available.
     */
    private static boolean sAlwaysAssignFocus;
    private String mTransitionName;
    static class TintInfo {
@@ -4810,6 +4815,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
            sCanFocusZeroSized = targetSdkVersion < Build.VERSION_CODES.P;
            sAlwaysAssignFocus = targetSdkVersion < Build.VERSION_CODES.P;
            sCompatibilityDone = true;
        }
    }
@@ -7000,8 +7007,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
     * Called when this view wants to give up focus. If focus is cleared
     * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} is called.
     * <p>
     * <strong>Note:</strong> When a View clears focus the framework is trying
     * to give focus to the first focusable View from the top. Hence, if this
     * <strong>Note:</strong> When not in touch-mode, the framework will try to give focus
     * to the first focusable View from the top after focus is cleared. Hence, if this
     * View is the first from the top that can take focus, then all callbacks
     * related to clearing focus will be invoked after which the framework will
     * give focus to this view.
@@ -7012,7 +7019,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
            System.out.println(this + " clearFocus()");
        }
        clearFocusInternal(null, true, true);
        final boolean refocus = sAlwaysAssignFocus || !isInTouchMode();
        clearFocusInternal(null, true, refocus);
    }
    /**
+4 −7
Original line number Diff line number Diff line
@@ -530,7 +530,7 @@ public final class ViewRootImpl implements ViewParent,
        mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE);

        if (!sCompatibilityDone) {
            sAlwaysAssignFocus = true;
            sAlwaysAssignFocus = mTargetSdkVersion < Build.VERSION_CODES.P;

            sCompatibilityDone = true;
        }
@@ -2337,7 +2337,7 @@ public final class ViewRootImpl implements ViewParent,
        }

        if (mFirst) {
            if (sAlwaysAssignFocus) {
            if (sAlwaysAssignFocus || !isInTouchMode()) {
                // handle first focus request
                if (DEBUG_INPUT_RESIZE) {
                    Log.v(mTag, "First: mView.hasFocus()=" + mView.hasFocus());
@@ -3608,7 +3608,7 @@ public final class ViewRootImpl implements ViewParent,
        checkThread();
        if (mView != null) {
            if (!mView.hasFocus()) {
                if (sAlwaysAssignFocus) {
                if (sAlwaysAssignFocus || !isInTouchMode()) {
                    v.requestFocus();
                }
            } else {
@@ -4211,10 +4211,7 @@ public final class ViewRootImpl implements ViewParent,

            // find the best view to give focus to in this brave new non-touch-mode
            // world
            final View focused = focusSearch(null, View.FOCUS_DOWN);
            if (focused != null) {
                return focused.requestFocus(View.FOCUS_DOWN);
            }
            return mView.restoreDefaultFocus();
        }
        return false;
    }