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

Commit 6c286bef authored by Evan Rosky's avatar Evan Rosky
Browse files

Only save focus in keyboard navigation clusters when appropriate

 - tabbing forward/backward should not save cluster focus. If
   focus leaves a cluster due to normal forward/backward navigation
   the cluster focus is cleared.
 - directional arrows or cluster jumps (meta+tab) will save focus
   in the cluster so that cluster-jumping back will restore it.

Also fixed a couple small bugs: focusable viewgroups wouldn't save
properly, focusIncluster wasn't cleared properly.

Bug: 35274351
Test: Added CTS test for this behavior.
Change-Id: Ie86218d70b0fc3aa1a709e613a2761a65ab12500
parent 2be0a532
Loading
Loading
Loading
Loading
+31 −6
Original line number Diff line number Diff line
@@ -6468,7 +6468,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
            if (mParent != null) {
                mParent.requestChildFocus(this, this);
                setFocusedInCluster();
                updateFocusedInCluster(oldFocus, direction);
            }
            if (mAttachInfo != null) {
@@ -9834,22 +9834,47 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
     * @hide
     */
    public final void setFocusedInCluster() {
        View top = findKeyboardNavigationCluster();
        if (top == this) {
        setFocusedInCluster(findKeyboardNavigationCluster());
    }
    private void setFocusedInCluster(View cluster) {
        if (this instanceof ViewGroup) {
            ((ViewGroup) this).mFocusedInCluster = null;
        }
        if (cluster == this) {
            return;
        }
        ViewParent parent = mParent;
        View child = this;
        while (parent instanceof ViewGroup) {
            ((ViewGroup) parent).setFocusedInCluster(child);
            if (parent == top) {
                return;
            ((ViewGroup) parent).mFocusedInCluster = child;
            if (parent == cluster) {
                break;
            }
            child = (View) parent;
            parent = parent.getParent();
        }
    }
    private void updateFocusedInCluster(View oldFocus, @FocusDirection int direction) {
        if (oldFocus != null) {
            View oldCluster = oldFocus.findKeyboardNavigationCluster();
            View cluster = findKeyboardNavigationCluster();
            if (oldCluster != cluster) {
                // Going from one cluster to another, so save last-focused.
                // This covers cluster jumps because they are always FOCUS_DOWN
                oldFocus.setFocusedInCluster(oldCluster);
                if (direction == FOCUS_FORWARD || direction == FOCUS_BACKWARD) {
                    // This is a result of ordered navigation so consider navigation through
                    // the previous cluster "complete" and clear its last-focused memory.
                    if (oldFocus.mParent instanceof ViewGroup) {
                        ((ViewGroup) oldFocus.mParent).clearFocusedInCluster(oldFocus);
                    }
                }
            }
        }
    }
    /**
     * Returns whether this View should receive focus when the focus is restored for the view
     * hierarchy containing this view.
+5 −6
Original line number Diff line number Diff line
@@ -143,7 +143,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
    // 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;
    View mFocusedInCluster;

    /**
     * A Transformation used when drawing children, to
@@ -807,10 +807,6 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
        return mDefaultFocus != null || super.hasDefaultFocus();
    }

    void setFocusedInCluster(View child) {
        mFocusedInCluster = child;
    }

    /**
     * Removes {@code child} (and associated focusedInCluster chain) from the cluster containing
     * it.
@@ -826,8 +822,11 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
        ViewParent parent = this;
        do {
            ((ViewGroup) parent).mFocusedInCluster = null;
            if (parent == top) {
                break;
            }
            parent = parent.getParent();
        } while (parent != top && parent instanceof ViewGroup);
        } while (parent instanceof ViewGroup);
    }

    @Override