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

Commit 0b1a4fbf authored by Daniel Norman's avatar Daniel Norman
Browse files

Expand the a11y focus bounds if they're too small to be visible.

Attempting to draw the focus drawable with bounds that are smaller
than 2 times the focus stroke size results in it being invisible.
Normally Views shouldn't be this thin in the first place, but this
change helps ensure the focus is visible when drawn over those edge
case ultra-thin Views.

See the bug comment 10 for screenshots of the fix.

Flag: android.view.accessibility.focus_rect_min_size
Test: atest FrameworksCoreTests:ViewRootImplTest
Test: Open problem app from bug, observe focus rect is now visible
Bug: 368667566
Change-Id: I5261cbd980d2a11a28a755756a4104ac2a349870
parent 562064be
Loading
Loading
Loading
Loading
+28 −1
Original line number Diff line number Diff line
@@ -5945,7 +5945,34 @@ public final class ViewRootImpl implements ViewParent,
            // If no intersection, set bounds to empty.
            bounds.setEmpty();
        }
        return !bounds.isEmpty();
        if (bounds.isEmpty()) {
            return false;
        }
        if (android.view.accessibility.Flags.focusRectMinSize()) {
            adjustAccessibilityFocusedRectBoundsIfNeeded(bounds);
        }
        return true;
    }
    /**
     * Adjusts accessibility focused rect bounds so that they are not invisible.
     *
     * <p>Focus bounds smaller than double the stroke width are very hard to see (or invisible).
     * Expand the focus bounds if necessary to at least double the stroke width.
     * @param bounds The bounds to adjust
     */
    @VisibleForTesting
    public void adjustAccessibilityFocusedRectBoundsIfNeeded(Rect bounds) {
        final int minRectLength = mAccessibilityManager.getAccessibilityFocusStrokeWidth() * 2;
        if (bounds.width() < minRectLength || bounds.height() < minRectLength) {
            final float missingWidth = Math.max(0, minRectLength - bounds.width());
            final float missingHeight = Math.max(0, minRectLength - bounds.height());
            bounds.inset(-1 * (int) Math.ceil(missingWidth / 2),
                    -1 * (int) Math.ceil(missingHeight / 2));
        }
    }
    private Drawable getAccessibilityFocusedDrawable() {
+10 −0
Original line number Diff line number Diff line
@@ -87,6 +87,16 @@ flag {
    bug: "303131332"
}

flag {
    namespace: "accessibility"
    name: "focus_rect_min_size"
    description: "Ensures the a11y focus rect is big enough to be drawn as visible"
    bug: "368667566"
    metadata {
        purpose: PURPOSE_BUGFIX
    }
}

flag {
    namespace: "accessibility"
    name: "force_invert_color"
+38 −0
Original line number Diff line number Diff line
@@ -71,6 +71,7 @@ import android.graphics.Rect;
import android.hardware.display.DisplayManagerGlobal;
import android.os.Binder;
import android.os.SystemProperties;
import android.platform.test.annotations.EnableFlags;
import android.platform.test.annotations.Presubmit;
import android.platform.test.annotations.RequiresFlagsEnabled;
import android.platform.test.flag.junit.CheckFlagsRule;
@@ -82,6 +83,7 @@ import android.util.DisplayMetrics;
import android.util.Log;
import android.view.WindowInsets.Side;
import android.view.WindowInsets.Type;
import android.view.accessibility.AccessibilityManager;

import androidx.test.annotation.UiThreadTest;
import androidx.test.ext.junit.runners.AndroidJUnit4;
@@ -1628,6 +1630,42 @@ public class ViewRootImplTest {
        });
    }

    @Test
    @EnableFlags(android.view.accessibility.Flags.FLAG_FOCUS_RECT_MIN_SIZE)
    public void testAdjustAccessibilityFocusedBounds_largeEnoughBoundsAreUnchanged() {
        final int strokeWidth = sContext.getSystemService(AccessibilityManager.class)
                .getAccessibilityFocusStrokeWidth();
        final int left, top, width, height;
        left = top = 100;
        width = height = strokeWidth * 2;
        final Rect bounds = new Rect(left, top, left + width, top + height);
        final Rect originalBounds = new Rect(bounds);

        mViewRootImpl.adjustAccessibilityFocusedRectBoundsIfNeeded(bounds);

        assertThat(bounds).isEqualTo(originalBounds);
    }

    @Test
    @EnableFlags(android.view.accessibility.Flags.FLAG_FOCUS_RECT_MIN_SIZE)
    public void testAdjustAccessibilityFocusedBounds_smallBoundsAreExpanded() {
        final int strokeWidth = sContext.getSystemService(AccessibilityManager.class)
                .getAccessibilityFocusStrokeWidth();
        final int left, top, width, height;
        left = top = 100;
        width = height = strokeWidth;
        final Rect bounds = new Rect(left, top, left + width, top + height);
        final Rect originalBounds = new Rect(bounds);

        mViewRootImpl.adjustAccessibilityFocusedRectBoundsIfNeeded(bounds);

        // Bounds should be centered on the same point, but expanded to at least strokeWidth * 2
        assertThat(bounds.centerX()).isEqualTo(originalBounds.centerX());
        assertThat(bounds.centerY()).isEqualTo(originalBounds.centerY());
        assertThat(bounds.width()).isAtLeast(strokeWidth * 2);
        assertThat(bounds.height()).isAtLeast(strokeWidth * 2);
    }

    private boolean setForceDarkSysProp(boolean isForceDarkEnabled) {
        try {
            SystemProperties.set(