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

Commit 8ce2d78a authored by Svetoslav Ganov's avatar Svetoslav Ganov Committed by Android (Google) Code Review
Browse files

Merge "Improving accessibility focus traversal." into jb-dev

parents a827843f e5dfa47d
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -330,7 +330,7 @@ final class AccessibilityInteractionController {
                                if (provider != null) {
                                    List<AccessibilityNodeInfo> infosFromProvider =
                                        provider.findAccessibilityNodeInfosByText(text,
                                                virtualDescendantId);
                                                AccessibilityNodeInfo.UNDEFINED);
                                    if (infosFromProvider != null) {
                                        infos.addAll(infosFromProvider);
                                    }
+8 −2
Original line number Diff line number Diff line
@@ -276,8 +276,11 @@ public class FocusFinder {
                return focusables.get(position + 1);
            }
        }
        if (!focusables.isEmpty()) {
            return focusables.get(0);
        }
        return null;
    }

    private static View getBackwardFocusable(ViewGroup root, View focused,
                                             ArrayList<View> focusables, int count) {
@@ -293,8 +296,11 @@ public class FocusFinder {
                return focusables.get(position - 1);
            }
        }
        if (!focusables.isEmpty()) {
            return focusables.get(count - 1);
        }
        return null;
    }

    /**
     * Is rect1 a better candidate than rect2 for a focus search in a particular
+24 −51
Original line number Diff line number Diff line
@@ -6027,8 +6027,7 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
            return;
        }
        if ((focusableMode & FOCUSABLES_ACCESSIBILITY) == FOCUSABLES_ACCESSIBILITY) {
            if (AccessibilityManager.getInstance(mContext).isEnabled()
                    && includeForAccessibility()) {
            if (canTakeAccessibilityFocusFromHover()) {
                views.add(this);
                return;
            }
@@ -6181,57 +6180,28 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
        }
    }
    /**
     * Find the best view to take accessibility focus from a hover.
     * This function finds the deepest actionable view and if that
     * fails ask the parent to take accessibility focus from hover.
     *
     * @param x The X hovered location in this view coorditantes.
     * @param y The Y hovered location in this view coorditantes.
     * @return Whether the request was handled.
     *
     * @hide
     */
    public boolean requestAccessibilityFocusFromHover(float x, float y) {
        if (onRequestAccessibilityFocusFromHover(x, y)) {
            return true;
    private void requestAccessibilityFocusFromHover() {
        if (includeForAccessibility() && isActionableForAccessibility()) {
            requestAccessibilityFocus();
        } else {
            if (mParent != null) {
                View nextFocus = mParent.findViewToTakeAccessibilityFocusFromHover(this, this);
                if (nextFocus != null) {
                    nextFocus.requestAccessibilityFocus();
                }
        ViewParent parent = mParent;
        if (parent instanceof View) {
            View parentView = (View) parent;
            float[] position = mAttachInfo.mTmpTransformLocation;
            position[0] = x;
            position[1] = y;
            // Compensate for the transformation of the current matrix.
            if (!hasIdentityMatrix()) {
                getMatrix().mapPoints(position);
            }
            // Compensate for the parent scroll and the offset
            // of this view stop from the parent top.
            position[0] += mLeft - parentView.mScrollX;
            position[1] += mTop - parentView.mScrollY;
            return parentView.requestAccessibilityFocusFromHover(position[0], position[1]);
        }
        return false;
    }
    /**
     * Requests to give this View focus from hover.
     *
     * @param x The X hovered location in this view coorditantes.
     * @param y The Y hovered location in this view coorditantes.
     * @return Whether the request was handled.
     *
     * @hide
     */
    public boolean onRequestAccessibilityFocusFromHover(float x, float y) {
        if (includeForAccessibility()
                && (isActionableForAccessibility() || hasListenersForAccessibility())) {
            return requestAccessibilityFocus();
    public boolean canTakeAccessibilityFocusFromHover() {
        if (includeForAccessibility() && isActionableForAccessibility()) {
            return true;
        }
        if (mParent != null) {
            return (mParent.findViewToTakeAccessibilityFocusFromHover(this, this) == this);
        }
        return false;
    }
@@ -6493,14 +6463,15 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
     * important for accessibility are regarded.
     *
     * @return Whether to regard the view for accessibility.
     *
     * @hide
     */
    boolean includeForAccessibility() {
    public boolean includeForAccessibility() {
        if (mAttachInfo != null) {
            if (!mAttachInfo.mIncludeNotImportantViews) {
                return isImportantForAccessibility();
            } else {
                return true;
            }
            return true;
        }
        return false;
    }
@@ -6511,8 +6482,10 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
     * accessiiblity.
     *
     * @return True if the view is actionable for accessibility.
     *
     * @hide
     */
    private boolean isActionableForAccessibility() {
    public boolean isActionableForAccessibility() {
        return (isClickable() || isLongClickable() || isFocusable());
    }
@@ -7688,7 +7661,7 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
                    && pointInView(event.getX(), event.getY())) {
                sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_HOVER_ENTER);
                mSendingHoverAccessibilityEvents = true;
                requestAccessibilityFocusFromHover((int) event.getX(), (int) event.getY());
                requestAccessibilityFocusFromHover();
            }
        } else {
            if (action == MotionEvent.ACTION_HOVER_EXIT
+25 −13
Original line number Diff line number Diff line
@@ -628,7 +628,11 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
     *        FOCUS_RIGHT, or 0 for not applicable.
     */
    public View focusSearch(View focused, int direction) {
        if (isRootNamespace()) {
        // If we are moving accessibility focus we want to consider all
        // views no matter if they are on the screen. It is responsibility
        // of the accessibility service to check whether the result is in
        // the screen.
        if (isRootNamespace() && (direction & FOCUS_ACCESSIBILITY) == 0) {
            // root namespace means we should consider ourselves the top of the
            // tree for focus searching; otherwise we could be focus searching
            // into other tabs.  see LocalActivityManager and TabHost for more info
@@ -853,14 +857,6 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
        return false;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void addFocusables(ArrayList<View> views, int direction) {
        addFocusables(views, direction, FOCUSABLES_TOUCH_MODE);
    }

    /**
     * {@inheritDoc}
     */
@@ -870,7 +866,8 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager

        final int descendantFocusability = getDescendantFocusability();

        if (descendantFocusability != FOCUS_BLOCK_DESCENDANTS) {
        if (descendantFocusability != FOCUS_BLOCK_DESCENDANTS
                || (focusableMode & FOCUSABLES_ACCESSIBILITY) == FOCUSABLES_ACCESSIBILITY) {
            final int count = mChildrenCount;
            final View[] children = mChildren;

@@ -886,10 +883,11 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
        // FOCUS_AFTER_DESCENDANTS and there are some descendants focusable.  this is
        // to avoid the focus search finding layouts when a more precise search
        // among the focusable children would be more interesting.
        if (
            descendantFocusability != FOCUS_AFTER_DESCENDANTS ||
        if (descendantFocusability != FOCUS_AFTER_DESCENDANTS
                // No focusable descendants
                (focusableCount == views.size())) {
                || (focusableCount == views.size())
                // We are collecting accessibility focusables.
                || (focusableMode & FOCUSABLES_ACCESSIBILITY) == FOCUSABLES_ACCESSIBILITY) {
            super.addFocusables(views, direction, focusableMode);
        }
    }
@@ -1658,6 +1656,20 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
        }
    }

    /**
     * @hide
     */
    @Override
    public View findViewToTakeAccessibilityFocusFromHover(View child, View descendant) {
        if (includeForAccessibility() && isActionableForAccessibility()) {
            return this;
        }
        if (mParent != null) {
            return mParent.findViewToTakeAccessibilityFocusFromHover(this, descendant);
        }
        return null;
    }

    /**
     * Implement this method to intercept hover events before they are handled
     * by child views.
+12 −0
Original line number Diff line number Diff line
@@ -295,4 +295,16 @@ public interface ViewParent {
     * @hide
     */
    public void childAccessibilityStateChanged(View child);

    /**
     * A descendant requests this view to find a candidate to take accessibility
     * focus from hover.
     *
     * @param child The child making the call.
     * @param descendant The descendant that made the initial request.
     * @return A view to take accessibility focus.
     *
     * @hide
     */
    public View findViewToTakeAccessibilityFocusFromHover(View child, View descendant);
}
Loading