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
diff --git a/src/com/android/launcher3/CheckLongPressHelper.java b/src/com/android/launcher3/CheckLongPressHelper.java
index c707df0..ec29b29 100644
--- a/src/com/android/launcher3/CheckLongPressHelper.java
+++ b/src/com/android/launcher3/CheckLongPressHelper.java
@@ -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 @@
private float mLongPressTimeoutFactor = DEFAULT_LONG_PRESS_TIMEOUT_FACTOR;
private boolean mHasPerformedLongPress;
+ private boolean mIsInMouseRightClick;
private Runnable mPendingCheckForLongPress;
@@ -59,6 +63,26 @@
// 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 @@
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 @@
}
/**
- * 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 @@
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);
+ }
}