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

Commit 5e004273 authored by Gavin Williams's avatar Gavin Williams Committed by Android (Google) Code Review
Browse files

Merge changes I2049c693,Idb408103 into main

* changes:
  a11y: Force left click when autoclick panel hovered
  a11y: Add test coverage for autoclick click type
parents 8971f375 3049283f
Loading
Loading
Loading
Loading
+20 −9
Original line number Diff line number Diff line
@@ -248,7 +248,11 @@ public class AutoclickController extends BaseEventStreamTransformation {

    private boolean isPaused() {
        return Flags.enableAutoclickIndicator() && mAutoclickTypePanel.isPaused()
                && !mAutoclickTypePanel.isHovered();
                && !isHovered();
    }

    private boolean isHovered() {
        return Flags.enableAutoclickIndicator() && mAutoclickTypePanel.isHovered();
    }

    private void cancelPendingClick() {
@@ -495,6 +499,8 @@ public class AutoclickController extends BaseEventStreamTransformation {
        private int mEventPolicyFlags;
        /** Current meta state. This value will be used as meta state for click event sequence. */
        private int mMetaState;
        /** Last observed panel hovered state when click was scheduled. */
        private boolean mHoveredState;

        /**
         * The current anchor's coordinates. Should be ignored if #mLastMotionEvent is null.
@@ -648,6 +654,7 @@ public class AutoclickController extends BaseEventStreamTransformation {
            }
            mLastMotionEvent = MotionEvent.obtain(event);
            mEventPolicyFlags = policyFlags;
            mHoveredState = isHovered();

            if (useAsAnchor) {
                final int pointerIndex = mLastMotionEvent.getActionIndex();
@@ -729,14 +736,18 @@ public class AutoclickController extends BaseEventStreamTransformation {

            final long now = SystemClock.uptimeMillis();

            // TODO(b/395094903): always triggers left-click when the cursor hovers over the
            // autoclick type panel, to always allow users to change a different click type.
            // Otherwise, if one chooses the right-click, this user won't be able to rely on
            // autoclick to select other click types.
            final int actionButton =
                    mActiveClickType == AUTOCLICK_TYPE_RIGHT_CLICK
            int actionButton;
            if (mHoveredState) {
                // Always triggers left-click when the cursor hovers over the autoclick type
                // panel, to always allow users to change a different click type. Otherwise, if
                // one chooses the right-click, this user won't be able to rely on autoclick to
                // select other click types.
                actionButton = BUTTON_PRIMARY;
            } else {
                actionButton = mActiveClickType == AUTOCLICK_TYPE_RIGHT_CLICK
                        ? BUTTON_SECONDARY
                        : BUTTON_PRIMARY;
            }

            MotionEvent downEvent =
                    MotionEvent.obtain(
+108 −0
Original line number Diff line number Diff line
@@ -43,6 +43,7 @@ import android.view.accessibility.AccessibilityManager;

import com.android.internal.accessibility.util.AccessibilityUtils;
import com.android.server.accessibility.AccessibilityTraceManager;
import com.android.server.accessibility.BaseEventStreamTransformation;

import org.junit.After;
import org.junit.Before;
@@ -70,6 +71,19 @@ public class AutoclickControllerTest {
    @Mock private WindowManager mMockWindowManager;
    private AutoclickController mController;

    private static class MotionEventCaptor extends BaseEventStreamTransformation {
        public MotionEvent downEvent;

        @Override
        public void onMotionEvent(MotionEvent event, MotionEvent rawEvent, int policyFlags) {
            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    downEvent = event;
                    break;
            }
        }
    }

    @Before
    public void setUp() {
        mTestableLooper = TestableLooper.get(this);
@@ -713,6 +727,100 @@ public class AutoclickControllerTest {
        assertThat(mController.mAutoclickScrollPanel.isVisible()).isFalse();
    }

    @Test
    public void sendClick_clickType_leftClick() {
        MotionEventCaptor motionEventCaptor = new MotionEventCaptor();
        mController.setNext(motionEventCaptor);

        injectFakeMouseActionHoverMoveEvent();
        // Set delay to zero so click is scheduled to run immediately.
        mController.mClickScheduler.updateDelay(0);

        // Send hover move event.
        MotionEvent hoverMove = MotionEvent.obtain(
                /* downTime= */ 0,
                /* eventTime= */ 100,
                /* action= */ MotionEvent.ACTION_HOVER_MOVE,
                /* x= */ 30f,
                /* y= */ 0f,
                /* metaState= */ 0);
        hoverMove.setSource(InputDevice.SOURCE_MOUSE);
        mController.onMotionEvent(hoverMove, hoverMove, /* policyFlags= */ 0);
        mTestableLooper.processAllMessages();

        // Verify left click sent.
        assertThat(motionEventCaptor.downEvent).isNotNull();
        assertThat(motionEventCaptor.downEvent.getButtonState()).isEqualTo(
                MotionEvent.BUTTON_PRIMARY);
    }

    @Test
    public void sendClick_clickType_rightClick() {
        MotionEventCaptor motionEventCaptor = new MotionEventCaptor();
        mController.setNext(motionEventCaptor);

        injectFakeMouseActionHoverMoveEvent();
        // Set delay to zero so click is scheduled to run immediately.
        mController.mClickScheduler.updateDelay(0);

        // Set click type to right click.
        mController.clickPanelController.handleAutoclickTypeChange(
                AutoclickTypePanel.AUTOCLICK_TYPE_RIGHT_CLICK);

        // Send hover move event.
        MotionEvent hoverMove = MotionEvent.obtain(
                /* downTime= */ 0,
                /* eventTime= */ 100,
                /* action= */ MotionEvent.ACTION_HOVER_MOVE,
                /* x= */ 30f,
                /* y= */ 0f,
                /* metaState= */ 0);
        hoverMove.setSource(InputDevice.SOURCE_MOUSE);
        mController.onMotionEvent(hoverMove, hoverMove, /* policyFlags= */ 0);
        mTestableLooper.processAllMessages();

        // Verify right click sent.
        assertThat(motionEventCaptor.downEvent).isNotNull();
        assertThat(motionEventCaptor.downEvent.getButtonState()).isEqualTo(
                MotionEvent.BUTTON_SECONDARY);
    }

    @Test
    @EnableFlags(com.android.server.accessibility.Flags.FLAG_ENABLE_AUTOCLICK_INDICATOR)
    public void hoverOnAutoclickPanel_rightClickType_forceTriggerLeftClick() {
        MotionEventCaptor motionEventCaptor = new MotionEventCaptor();
        mController.setNext(motionEventCaptor);

        injectFakeMouseActionHoverMoveEvent();
        // Set delay to zero so click is scheduled to run immediately.
        mController.mClickScheduler.updateDelay(0);

        // Set click type to right click.
        mController.clickPanelController.handleAutoclickTypeChange(
                AutoclickTypePanel.AUTOCLICK_TYPE_RIGHT_CLICK);
        // Set mouse to hover panel.
        AutoclickTypePanel mockAutoclickTypePanel = mock(AutoclickTypePanel.class);
        when(mockAutoclickTypePanel.isHovered()).thenReturn(true);
        mController.mAutoclickTypePanel = mockAutoclickTypePanel;

        // Send hover move event.
        MotionEvent hoverMove = MotionEvent.obtain(
                /* downTime= */ 0,
                /* eventTime= */ 100,
                /* action= */ MotionEvent.ACTION_HOVER_MOVE,
                /* x= */ 30f,
                /* y= */ 0f,
                /* metaState= */ 0);
        hoverMove.setSource(InputDevice.SOURCE_MOUSE);
        mController.onMotionEvent(hoverMove, hoverMove, /* policyFlags= */ 0);
        mTestableLooper.processAllMessages();

        // Verify left click is sent due to the mouse hovering the panel.
        assertThat(motionEventCaptor.downEvent).isNotNull();
        assertThat(motionEventCaptor.downEvent.getButtonState()).isEqualTo(
                MotionEvent.BUTTON_PRIMARY);
    }

    private void injectFakeMouseActionHoverMoveEvent() {
        MotionEvent event = getFakeMotionHoverMoveEvent();
        event.setSource(InputDevice.SOURCE_MOUSE);