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

Commit b1986354 authored by Alan Viverette's avatar Alan Viverette Committed by Android Git Automerger
Browse files

am aad44178: Merge "Use transient state to preserve accessibility focus in ListView" into klp-dev

* commit 'aad44178':
  Use transient state to preserve accessibility focus in ListView
parents 37eb3034 aad44178
Loading
Loading
Loading
Loading
+2 −3
Original line number Diff line number Diff line
@@ -6680,8 +6680,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
     * Returns whether this View is accessibility focused.
     *
     * @return True if this View is accessibility focused.
     * @hide
     */
    boolean isAccessibilityFocused() {
    public boolean isAccessibilityFocused() {
        return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0;
    }
@@ -7389,7 +7390,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
     * @hide
     */
    public void dispatchStartTemporaryDetach() {
        clearAccessibilityFocus();
        clearDisplayList();
        onStartTemporaryDetach();
@@ -11860,7 +11860,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
        jumpDrawablesToCurrentState();
        clearAccessibilityFocus();
        resetSubtreeAccessibilityStateChanged();
        if (isFocused()) {
+37 −75
Original line number Diff line number Diff line
@@ -42,7 +42,6 @@ import android.view.ViewParent;
import android.view.ViewRootImpl;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
import android.view.accessibility.AccessibilityNodeProvider;
import android.widget.RemoteViews.RemoteView;

import java.util.ArrayList;
@@ -1507,10 +1506,6 @@ public class ListView extends AbsListView {
            View oldFirst = null;
            View newSel = null;

            AccessibilityNodeInfo accessibilityFocusLayoutRestoreNode = null;
            View accessibilityFocusLayoutRestoreView = null;
            int accessibilityFocusPosition = INVALID_POSITION;

            // Remember stuff we will need down below
            switch (mLayoutMode) {
            case LAYOUT_SET_SELECTION:
@@ -1565,31 +1560,14 @@ public class ListView extends AbsListView {

            setSelectedPositionInt(mNextSelectedPosition);

            // Remember which child, if any, had accessibility focus. This must
            // occur before recycling any views, since that will clear
            // accessibility focus.
            // TODO: This should rely on transient state.
            final ViewRootImpl viewRootImpl = getViewRootImpl();
            if (viewRootImpl != null) {
                final View accessFocusedView = viewRootImpl.getAccessibilityFocusedHost();
                if (accessFocusedView != null) {
                    final View accessFocusedChild = findAccessibilityFocusedChild(
                            accessFocusedView);
            // Remember which child, if any, had accessibility focus.
            final int accessibilityFocusPosition;
            final View accessFocusedChild = getAccessibilityFocusedChild();
            if (accessFocusedChild != null) {
                        if (!dataChanged || isDirectChildHeaderOrFooter(accessFocusedChild)) {
                            // If the views won't be changing, try to maintain
                            // focus on the current view host and (if
                            // applicable) its virtual view.
                            accessibilityFocusLayoutRestoreView = accessFocusedView;
                            accessibilityFocusLayoutRestoreNode = viewRootImpl
                                    .getAccessibilityFocusedVirtualView();
                        } else {
                            // Otherwise, try to maintain focus at the same
                            // position.
                accessibilityFocusPosition = getPositionForView(accessFocusedChild);
                        }
                    }
                }
                accessFocusedChild.setHasTransientState(true);
            } else {
                accessibilityFocusPosition = INVALID_POSITION;
            }

            // Ensure the child containing focus, if any, has transient state.
@@ -1704,27 +1682,22 @@ public class ListView extends AbsListView {
                }
            }

            // Attempt to restore accessibility focus.
            if (accessibilityFocusLayoutRestoreView != null) {
                final AccessibilityNodeProvider provider =
                        accessibilityFocusLayoutRestoreView.getAccessibilityNodeProvider();
                if ((accessibilityFocusLayoutRestoreNode != null) && (provider != null)) {
                    final int virtualViewId = AccessibilityNodeInfo.getVirtualDescendantId(
                            accessibilityFocusLayoutRestoreNode.getSourceNodeId());
                    provider.performAction(virtualViewId,
                            AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS, null);
                } else {
                    accessibilityFocusLayoutRestoreView.requestAccessibilityFocus();
                }
            } else if (accessibilityFocusPosition != INVALID_POSITION) {
            if (accessFocusedChild != null) {
                accessFocusedChild.setHasTransientState(false);

                // If we failed to maintain accessibility focus on the previous
                // view, attempt to restore it to the previous position.
                if (!accessFocusedChild.isAccessibilityFocused()
                    && accessibilityFocusPosition != INVALID_POSITION) {
                    // Bound the position within the visible children.
                    final int position = MathUtils.constrain(
                        (accessibilityFocusPosition - mFirstPosition), 0, (getChildCount() - 1));
                            accessibilityFocusPosition - mFirstPosition, 0, getChildCount() - 1);
                    final View restoreView = getChildAt(position);
                    if (restoreView != null) {
                        restoreView.requestAccessibilityFocus();
                    }
                }
            }

            if (focusedChild != null) {
                focusedChild.setHasTransientState(false);
@@ -1754,42 +1727,31 @@ public class ListView extends AbsListView {
    }

    /**
     * @param focusedView the view that has accessibility focus.
     * @return the direct child that contains accessibility focus.
     * @return the direct child that contains accessibility focus, or null if no
     *         child contains accessibility focus
     */
    private View findAccessibilityFocusedChild(View focusedView) {
    private View getAccessibilityFocusedChild() {
        final ViewRootImpl viewRootImpl = getViewRootImpl();
        if (viewRootImpl == null) {
            return null;
        }

        View focusedView = viewRootImpl.getAccessibilityFocusedHost();
        if (focusedView == null) {
            return null;
        }

        ViewParent viewParent = focusedView.getParent();
        while ((viewParent instanceof View) && (viewParent != this)) {
            focusedView = (View) viewParent;
            viewParent = viewParent.getParent();
        }

        if (!(viewParent instanceof View)) {
            return null;
        }
        return focusedView;
    }

    /**
     * @param child a direct child of this list.
     * @return Whether child is a header or footer view.
     */
    private boolean isDirectChildHeaderOrFooter(View child) {

        final ArrayList<FixedViewInfo> headers = mHeaderViewInfos;
        final int numHeaders = headers.size();
        for (int i = 0; i < numHeaders; i++) {
            if (child == headers.get(i).view) {
                return true;
            }
        }
        final ArrayList<FixedViewInfo> footers = mFooterViewInfos;
        final int numFooters = footers.size();
        for (int i = 0; i < numFooters; i++) {
            if (child == footers.get(i).view) {
                return true;
            }
        }
        return false;
        return focusedView;
    }

    /**