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

Commit 241cd23d authored by Yuhan Yang's avatar Yuhan Yang
Browse files

Implement double click as autoclick type

screencast: go/screencast-ndc1njczodi1mdexmzaynhw2mti1mmm1mi01yg

Bug: 388844955
Test: atest AutoclickControllerTest
Flag: com.android.server.accessibility.enable_autoclick_indicator
Change-Id: Ic0db436e65ab9de4758f6d3ac9d6e2559ec63bc7
parent 45a14a7d
Loading
Loading
Loading
Loading
+25 −6
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ import static android.view.accessibility.AccessibilityManager.AUTOCLICK_IGNORE_M
import static android.view.accessibility.AccessibilityManager.AUTOCLICK_REVERT_TO_LEFT_CLICK_DEFAULT;

import static com.android.server.accessibility.autoclick.AutoclickIndicatorView.SHOW_INDICATOR_DELAY_TIME;
import static com.android.server.accessibility.autoclick.AutoclickTypePanel.AUTOCLICK_TYPE_DOUBLE_CLICK;
import static com.android.server.accessibility.autoclick.AutoclickTypePanel.AUTOCLICK_TYPE_LEFT_CLICK;
import static com.android.server.accessibility.autoclick.AutoclickTypePanel.AUTOCLICK_TYPE_RIGHT_CLICK;
import static com.android.server.accessibility.autoclick.AutoclickTypePanel.AUTOCLICK_TYPE_SCROLL;
@@ -45,6 +46,7 @@ import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.MotionEvent.PointerCoords;
import android.view.MotionEvent.PointerProperties;
import android.view.ViewConfiguration;
import android.view.WindowManager;

import androidx.annotation.VisibleForTesting;
@@ -799,7 +801,7 @@ public class AutoclickController extends BaseEventStreamTransformation {

            final long now = SystemClock.uptimeMillis();

            int actionButton;
            int actionButton = BUTTON_PRIMARY;
            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
@@ -807,15 +809,32 @@ public class AutoclickController extends BaseEventStreamTransformation {
                // select other click types.
                actionButton = BUTTON_PRIMARY;
            } else {
                actionButton = mActiveClickType == AUTOCLICK_TYPE_RIGHT_CLICK
                        ? BUTTON_SECONDARY
                        : BUTTON_PRIMARY;
                switch (mActiveClickType) {
                    case AUTOCLICK_TYPE_LEFT_CLICK:
                        actionButton = BUTTON_PRIMARY;
                        break;
                    case AUTOCLICK_TYPE_RIGHT_CLICK:
                        actionButton = BUTTON_SECONDARY;
                        break;
                    case AUTOCLICK_TYPE_DOUBLE_CLICK:
                        actionButton = BUTTON_PRIMARY;
                        long doubleTapMinimumTimeout = ViewConfiguration.getDoubleTapMinTime();
                        sendMotionEvent(actionButton, now);
                        sendMotionEvent(actionButton, now + doubleTapMinimumTimeout);
                        return;
                    default:
                        break;
                }
            }

            sendMotionEvent(actionButton, now);
        }

        private void sendMotionEvent(int actionButton, long eventTime) {
            MotionEvent downEvent =
                    MotionEvent.obtain(
                            /* downTime= */ now,
                            /* eventTime= */ now,
                            /* downTime= */ eventTime,
                            /* eventTime= */ eventTime,
                            MotionEvent.ACTION_DOWN,
                            /* pointerCount= */ 1,
                            mTempPointerProperties,
+37 −1
Original line number Diff line number Diff line
@@ -75,12 +75,13 @@ public class AutoclickControllerTest {

    private static class MotionEventCaptor extends BaseEventStreamTransformation {
        public MotionEvent downEvent;

        public int eventCount = 0;
        @Override
        public void onMotionEvent(MotionEvent event, MotionEvent rawEvent, int policyFlags) {
            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    downEvent = event;
                    eventCount++;
                    break;
            }
        }
@@ -922,6 +923,41 @@ public class AutoclickControllerTest {
        mController.onKeyEvent(keyEvent, /* policyFlags= */ 0);
    }

    @Test
    @EnableFlags(com.android.server.accessibility.Flags.FLAG_ENABLE_AUTOCLICK_INDICATOR)
    public void sendClick_clickType_doubleclick_triggerClickTwice() {
        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 double click.
        mController.clickPanelController.handleAutoclickTypeChange(
                AutoclickTypePanel.AUTOCLICK_TYPE_DOUBLE_CLICK);
        AutoclickTypePanel mockAutoclickTypePanel = mock(AutoclickTypePanel.class);
        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 sent.
        assertThat(motionEventCaptor.downEvent).isNotNull();
        assertThat(motionEventCaptor.downEvent.getButtonState()).isEqualTo(
                MotionEvent.BUTTON_PRIMARY);
        assertThat(motionEventCaptor.eventCount).isEqualTo(2);
    }

    private MotionEvent getFakeMotionHoverMoveEvent() {
        return MotionEvent.obtain(
                /* downTime= */ 0,