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

Commit 9f90efb3 authored by Fengjiang Li's avatar Fengjiang Li
Browse files

Support right click to bring up app menu and actions

Test: https://b.corp.google.com/action/issues/250092449/attachments/40159735?download=true
Change-Id: I159005cc982478896d442bb2675ccb1bb7f0322e
parent 9adbab96
Loading
Loading
Loading
Loading
+39 −3
Original line number Diff line number Diff line
@@ -16,12 +16,15 @@

package com.android.launcher3;

import android.os.Handler;
import android.view.InputDevice;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;

/**
 * Utility class to handle tripper long press on a view with custom timeout and stylus event
 * Utility class to handle tripper long press or right click on a view with custom timeout and
 * stylus event
 */
public class CheckLongPressHelper {

@@ -34,6 +37,7 @@ public class CheckLongPressHelper {
    private float mLongPressTimeoutFactor = DEFAULT_LONG_PRESS_TIMEOUT_FACTOR;

    private boolean mHasPerformedLongPress;
    private boolean mIsInMouseRightClick;

    private Runnable mPendingCheckForLongPress;

@@ -59,6 +63,26 @@ public class CheckLongPressHelper {
                // start fresh on touch down.
                cancelLongPress();

                // Mouse right click should immediately trigger a long press
                if (isMouseRightClickDownOrMove(ev)) {
                    mIsInMouseRightClick = true;
                    triggerLongPress();
                    final Handler handler = mView.getHandler();
                    if (handler != null) {
                        // Send an ACTION_UP to end this click gesture to avoid user dragging with
                        // mouse's right button. Note that we need to call
                        // {@link Handler#postAtFrontOfQueue()} instead of {@link View#post()} to
                        // make sure ACTION_UP is sent before any ACTION_MOVE if user is dragging.
                        final MotionEvent actionUpEvent = MotionEvent.obtain(ev);
                        actionUpEvent.setAction(MotionEvent.ACTION_UP);
                        handler.postAtFrontOfQueue(() -> {
                            mView.getRootView().dispatchTouchEvent(actionUpEvent);
                            actionUpEvent.recycle();
                        });
                    }
                    break;
                }

                postCheckForLongPress();
                if (isStylusButtonPressed(ev)) {
                    triggerLongPress();
@@ -70,7 +94,8 @@ public class CheckLongPressHelper {
                cancelLongPress();
                break;
            case MotionEvent.ACTION_MOVE:
                if (!Utilities.pointInView(mView, ev.getX(), ev.getY(), mSlop)) {
                if (mIsInMouseRightClick
                        || !Utilities.pointInView(mView, ev.getX(), ev.getY(), mSlop)) {
                    cancelLongPress();
                } else if (mPendingCheckForLongPress != null && isStylusButtonPressed(ev)) {
                    // Only trigger long press if it has not been cancelled before
@@ -98,9 +123,10 @@ public class CheckLongPressHelper {
    }

    /**
     * Cancels any pending long press
     * Cancels any pending long press and right click
     */
    public void cancelLongPress() {
        mIsInMouseRightClick = false;
        mHasPerformedLongPress = false;
        clearCallbacks();
    }
@@ -150,4 +176,14 @@ public class CheckLongPressHelper {
        return event.getToolType(0) == MotionEvent.TOOL_TYPE_STYLUS
                && event.isButtonPressed(MotionEvent.BUTTON_SECONDARY);
    }

    /**
     * Detect ACTION_DOWN or ACTION_MOVE from mouse right button. Note that we cannot detect
     * ACTION_UP from mouse's right button because, in that case,
     * {@link MotionEvent#getButtonState()} returns 0 for any mouse button (right, middle, right).
     */
    private static boolean isMouseRightClickDownOrMove(MotionEvent event) {
        return event.isFromSource(InputDevice.SOURCE_MOUSE)
                && ((event.getButtonState() & MotionEvent.BUTTON_SECONDARY) != 0);
    }
}