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

Commit f9817f7a authored by Svetoslav Ganov's avatar Svetoslav Ganov
Browse files

Adding accessibility focusable attribute (hidden for now).

1. This attribute specifies whether a view can take accessibility
   focus. It has three values: 1) auto - the system determines
   based on whether the view is actionable and has actionable
   predecessor. Accessibility services can put accessibility focus
   on such a node at will; 2) yes ; this view always takes access
   focus; 3) no - the view cannot takes accessibility focus and
   accessibility services cannot put accessibility focus on it.

Change-Id: I2ebf4e7c75bf6b39e1742b6868b37ccdd4cc7d28
parent a587b890
Loading
Loading
Loading
Loading
+149 −11
Original line number Diff line number Diff line
@@ -2086,7 +2086,8 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
    // Accessiblity constants for mPrivateFlags2
    /**
     * Shift for accessibility related bits in {@link #mPrivateFlags2}.
     * Shift for the bits in {@link #mPrivateFlags2} related to the
     * "importantForAccessibility" attribute.
     */
    static final int IMPORTANT_FOR_ACCESSIBILITY_SHIFT = 20;
@@ -2142,6 +2143,72 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
     */
    static final int VIEW_QUICK_REJECTED = 0x20000000;
    // Accessiblity constants for mPrivateFlags2
    /**
     * Shift for the bits in {@link #mPrivateFlags2} related to the
     * "accessibilityFocusable" attribute.
     */
    static final int ACCESSIBILITY_FOCUSABLE_SHIFT = 30;
    /**
     * The system determines whether the view can take accessibility focus - default (recommended).
     * <p>
     * Such a view is consideted by the focus search if it is:
     * <ul>
     * <li>
     * Important for accessibility and actionable (clickable, long clickable, focusable)
     * </li>
     * <li>
     * Important for accessibility, not actionable (clickable, long clickable, focusable),
     * and does not have an actionable predecessor.
     * </li>
     * </ul>
     * An accessibility srvice can request putting accessibility focus on such a view.
     * </p>
     *
     * @hide
     */
    public static final int ACCESSIBILITY_FOCUSABLE_AUTO = 0x00000000;
    /**
     * The view can take accessibility focus.
     * <p>
     * A view that can take accessibility focus is always considered during focus
     * search and an accessibility service can request putting accessibility focus
     * on it.
     * </p>
     *
     * @hide
     */
    public static final int ACCESSIBILITY_FOCUSABLE_YES = 0x00000001;
    /**
     * The view can not take accessibility focus.
     * <p>
     * A view that can not take accessibility focus is never considered during focus
     * search and an accessibility service can not request putting accessibility focus
     * on it.
     * </p>
     *
     * @hide
     */
    public static final int ACCESSIBILITY_FOCUSABLE_NO = 0x00000002;
    /**
     * The default whether the view is accessiblity focusable.
     */
    static final int ACCESSIBILITY_FOCUSABLE_DEFAULT = ACCESSIBILITY_FOCUSABLE_AUTO;
    /**
     * Mask for obtainig the bits which specifies how to determine
     * whether a view is accessibility focusable.
     */
    static final int ACCESSIBILITY_FOCUSABLE_MASK = (ACCESSIBILITY_FOCUSABLE_AUTO
        | ACCESSIBILITY_FOCUSABLE_YES | ACCESSIBILITY_FOCUSABLE_NO)
        << ACCESSIBILITY_FOCUSABLE_SHIFT;
    /* End of masks for mPrivateFlags2 */
    static final int DRAG_MASK = DRAG_CAN_ACCEPT | DRAG_HOVERED;
@@ -3132,7 +3199,8 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
        mPrivateFlags2 = (LAYOUT_DIRECTION_DEFAULT << LAYOUT_DIRECTION_MASK_SHIFT) |
                (TEXT_DIRECTION_DEFAULT << TEXT_DIRECTION_MASK_SHIFT) |
                (TEXT_ALIGNMENT_DEFAULT << TEXT_ALIGNMENT_MASK_SHIFT) |
                (IMPORTANT_FOR_ACCESSIBILITY_DEFAULT << IMPORTANT_FOR_ACCESSIBILITY_SHIFT);
                (IMPORTANT_FOR_ACCESSIBILITY_DEFAULT << IMPORTANT_FOR_ACCESSIBILITY_SHIFT) |
                (ACCESSIBILITY_FOCUSABLE_DEFAULT << ACCESSIBILITY_FOCUSABLE_SHIFT);
        mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
        setOverScrollMode(OVER_SCROLL_IF_CONTENT_SCROLLS);
        mUserPaddingStart = -1;
@@ -4788,7 +4856,10 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
        }
        if (!isAccessibilityFocused()) {
            final int mode = getAccessibilityFocusable();
            if (mode == ACCESSIBILITY_FOCUSABLE_YES || mode == ACCESSIBILITY_FOCUSABLE_AUTO) {
                info.addAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS);
            }
        } else {
            info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
        }
@@ -6069,7 +6140,7 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
            return;
        }
        if ((focusableMode & FOCUSABLES_ACCESSIBILITY) == FOCUSABLES_ACCESSIBILITY) {
            if (canTakeAccessibilityFocusFromHover() || getAccessibilityNodeProvider() != null) {
            if (isAccessibilityFocusable()) {
                views.add(this);
                return;
            }
@@ -6403,12 +6474,9 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
     * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
     */
    @ViewDebug.ExportedProperty(category = "accessibility", mapping = {
            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_AUTO,
                    to = "IMPORTANT_FOR_ACCESSIBILITY_AUTO"),
            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_YES,
                    to = "IMPORTANT_FOR_ACCESSIBILITY_YES"),
            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO,
                    to = "IMPORTANT_FOR_ACCESSIBILITY_NO")
            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_AUTO, to = "auto"),
            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_YES, to = "yes"),
            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO, to = "no")
        })
    public int getImportantForAccessibility() {
        return (mPrivateFlags2 & IMPORTANT_FOR_ACCESSIBILITY_MASK)
@@ -6460,6 +6528,73 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
        }
    }
    /**
     * Gets the mode for determining whether this View can take accessibility focus.
     *
     * @return The mode for determining whether a View can take accessibility focus.
     *
     * @attr ref android.R.styleable#View_accessibilityFocusable
     *
     * @see #ACCESSIBILITY_FOCUSABLE_YES
     * @see #ACCESSIBILITY_FOCUSABLE_NO
     * @see #ACCESSIBILITY_FOCUSABLE_AUTO
     *
     * @hide
     */
    @ViewDebug.ExportedProperty(category = "accessibility", mapping = {
            @ViewDebug.IntToString(from = ACCESSIBILITY_FOCUSABLE_AUTO, to = "auto"),
            @ViewDebug.IntToString(from = ACCESSIBILITY_FOCUSABLE_YES, to = "yes"),
            @ViewDebug.IntToString(from = ACCESSIBILITY_FOCUSABLE_NO, to = "no")
        })
    public int getAccessibilityFocusable() {
        return (mPrivateFlags2 & ACCESSIBILITY_FOCUSABLE_MASK) >>> ACCESSIBILITY_FOCUSABLE_SHIFT;
    }
    /**
     * Sets how to determine whether this view can take accessibility focus.
     *
     * @param mode How to determine whether this view can take accessibility focus.
     *
     * @attr ref android.R.styleable#View_accessibilityFocusable
     *
     * @see #ACCESSIBILITY_FOCUSABLE_YES
     * @see #ACCESSIBILITY_FOCUSABLE_NO
     * @see #ACCESSIBILITY_FOCUSABLE_AUTO
     *
     * @hide
     */
    public void setAccessibilityFocusable(int mode) {
        if (mode != getAccessibilityFocusable()) {
            mPrivateFlags2 &= ~ACCESSIBILITY_FOCUSABLE_MASK;
            mPrivateFlags2 |= (mode << ACCESSIBILITY_FOCUSABLE_SHIFT)
                    & ACCESSIBILITY_FOCUSABLE_MASK;
            notifyAccessibilityStateChanged();
        }
    }
    /**
     * Gets whether this view can take accessibility focus.
     *
     * @return Whether the view can take accessibility focus.
     *
     * @hide
     */
    public boolean isAccessibilityFocusable() {
        final int mode = (mPrivateFlags2 & ACCESSIBILITY_FOCUSABLE_MASK)
                >>> ACCESSIBILITY_FOCUSABLE_SHIFT;
        switch (mode) {
            case ACCESSIBILITY_FOCUSABLE_YES:
                return true;
            case ACCESSIBILITY_FOCUSABLE_NO:
                return false;
            case ACCESSIBILITY_FOCUSABLE_AUTO:
                return canTakeAccessibilityFocusFromHover()
                        || getAccessibilityNodeProvider() != null;
            default:
                throw new IllegalArgumentException("Unknow accessibility focusable mode: " + mode);
        }
    }
    /**
     * Gets the parent for accessibility purposes. Note that the parent for
     * accessibility is not necessary the immediate parent. It is the first
@@ -6641,7 +6776,10 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
                }
            } break;
            case AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS: {
                if (!isAccessibilityFocused()) {
                final int mode = getAccessibilityFocusable();
                if (!isAccessibilityFocused()
                        && (mode == ACCESSIBILITY_FOCUSABLE_YES
                                || mode == ACCESSIBILITY_FOCUSABLE_AUTO)) {
                    return requestAccessibilityFocus();
                }
            } break;
+36 −1
Original line number Diff line number Diff line
@@ -2136,7 +2136,8 @@
             query the screen. Note: While not recommended, an accessibility service may
             decide to ignore this attribute and operate on all views in the view tree. -->
        <attr name="importantForAccessibility" format="integer">
            <!-- The system determines whether the view is important for accessibility (recommended). -->
            <!-- The system determines whether the view is important for accessibility - default
                 (recommended). -->
            <enum name="auto" value="0" />
            <!-- The view is important for accessibility. -->
            <enum name="yes" value="1" />
@@ -2144,6 +2145,40 @@
            <enum name="no" value="2" />
        </attr>

        <!-- @hide Controls whether this view can take accessibility focus. -->
        <attr name="accessibilityFocusable" format="integer">
            <!-- The system determines whether the view can take accessibility focus - default
                 (recommended).
                 <p>
                 Such a view is consideted by the focus search if it is:
                 <ul>
                 <li>
                 Important for accessibility and actionable (clickable, long clickable, focusable)
                 </li>
                 <li>
                 Important for accessibility, not actionable (clickable, long clickable, focusable),
                 and does not have an actionable predecessor.
                 </li>
                 </ul>
                 An accessibility srvice can request putting accessibility focus on such a view.
                 </p> -->
            <enum name="auto" value="0" />
            <!-- The view can take accessibility focus.
                 <p>
                 A view that can take accessibility focus is always considered during focus
                 search and an accessibility service can request putting accessibility focus
                 on it.
                 </p> -->
            <enum name="yes" value="1" />
            <!-- The view can not take accessibility focus.
                 <p>
                 A view that can not take accessibility focus is never considered during focus
                 search and an accessibility service can not request putting accessibility focus
                 on it.
                 </p> -->
            <enum name="no" value="2" />
        </attr>

    </declare-styleable>

    <!-- Attributes that can be used with a {@link android.view.ViewGroup} or any