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

Commit 13b432cd authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Support right click to bring up app menu and actions" into tm-qpr-dev

parents abb18ea6 9f90efb3
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);
    }
}