From a6a67e347dbd5e8e1f9b5808f897f657643bdae6 Mon Sep 17 00:00:00 2001 From: Fengjiang Li Date: Tue, 6 Dec 2022 21:53:25 -0800 Subject: [PATCH] Support mouse right click on HomeScreen to show the customization menu Bug: b/250089861 Fix: b/250089861 Test: Manual Testing Video: https://b.corp.google.com/action/issues/250089861/attachments/40243664?download=true Change-Id: Ia23e302bf8f3e18fafd6ccd079740c8005ae7860 --- .../launcher3/CheckLongPressHelper.java | 15 +---- .../touch/WorkspaceTouchListener.java | 10 +++ src/com/android/launcher3/util/TouchUtil.java | 37 ++++++++++ .../android/launcher3/util/TouchUtilTest.kt | 67 +++++++++++++++++++ 4 files changed, 117 insertions(+), 12 deletions(-) create mode 100644 src/com/android/launcher3/util/TouchUtil.java create mode 100644 tests/src/com/android/launcher3/util/TouchUtilTest.kt diff --git a/src/com/android/launcher3/CheckLongPressHelper.java b/src/com/android/launcher3/CheckLongPressHelper.java index ec29b297a9..3e4e96bec0 100644 --- a/src/com/android/launcher3/CheckLongPressHelper.java +++ b/src/com/android/launcher3/CheckLongPressHelper.java @@ -17,11 +17,12 @@ package com.android.launcher3; import android.os.Handler; -import android.view.InputDevice; import android.view.MotionEvent; import android.view.View; import android.view.ViewConfiguration; +import com.android.launcher3.util.TouchUtil; + /** * Utility class to handle tripper long press or right click on a view with custom timeout and * stylus event @@ -64,7 +65,7 @@ public class CheckLongPressHelper { cancelLongPress(); // Mouse right click should immediately trigger a long press - if (isMouseRightClickDownOrMove(ev)) { + if (TouchUtil.isMouseRightClickDownOrMove(ev)) { mIsInMouseRightClick = true; triggerLongPress(); final Handler handler = mView.getHandler(); @@ -176,14 +177,4 @@ 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); - } } diff --git a/src/com/android/launcher3/touch/WorkspaceTouchListener.java b/src/com/android/launcher3/touch/WorkspaceTouchListener.java index 6cb021bc42..96ae4a32fd 100644 --- a/src/com/android/launcher3/touch/WorkspaceTouchListener.java +++ b/src/com/android/launcher3/touch/WorkspaceTouchListener.java @@ -44,6 +44,7 @@ import com.android.launcher3.dragndrop.DragLayer; import com.android.launcher3.logger.LauncherAtom; import com.android.launcher3.testing.TestLogging; import com.android.launcher3.testing.shared.TestProtocol; +import com.android.launcher3.util.TouchUtil; /** * Helper class to handle touch on empty space in workspace and show options popup on long press @@ -105,6 +106,11 @@ public class WorkspaceTouchListener extends GestureDetector.SimpleOnGestureListe if (handleLongPress) { mLongPressState = STATE_REQUESTED; mTouchDownPoint.set(ev.getX(), ev.getY()); + // Mouse right button's ACTION_DOWN should immediately show menu + if (TouchUtil.isMouseRightClickDownOrMove(ev)) { + maybeShowMenu(); + return true; + } } mWorkspace.onTouchEvent(ev); @@ -185,6 +191,10 @@ public class WorkspaceTouchListener extends GestureDetector.SimpleOnGestureListe @Override public void onLongPress(MotionEvent event) { + maybeShowMenu(); + } + + private void maybeShowMenu() { if (mLongPressState == STATE_REQUESTED) { TestLogging.recordEvent(TestProtocol.SEQUENCE_MAIN, "Workspace.longPress"); if (canHandleLongPress()) { diff --git a/src/com/android/launcher3/util/TouchUtil.java b/src/com/android/launcher3/util/TouchUtil.java new file mode 100644 index 0000000000..b18a2ef485 --- /dev/null +++ b/src/com/android/launcher3/util/TouchUtil.java @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.launcher3.util; + +import android.view.InputDevice; +import android.view.MotionEvent; + +import androidx.annotation.NonNull; + +/** Util class for touch event. */ +public final class TouchUtil { + + private TouchUtil() {} + + /** + * 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). + */ + public static boolean isMouseRightClickDownOrMove(@NonNull MotionEvent event) { + return event.isFromSource(InputDevice.SOURCE_MOUSE) + && ((event.getButtonState() & MotionEvent.BUTTON_SECONDARY) != 0); + } +} diff --git a/tests/src/com/android/launcher3/util/TouchUtilTest.kt b/tests/src/com/android/launcher3/util/TouchUtilTest.kt new file mode 100644 index 0000000000..d6c6e91e49 --- /dev/null +++ b/tests/src/com/android/launcher3/util/TouchUtilTest.kt @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.launcher3.util + +import android.view.InputDevice +import android.view.MotionEvent +import androidx.test.filters.SmallTest +import com.google.common.truth.Truth.assertThat +import androidx.test.ext.junit.runners.AndroidJUnit4 +import org.junit.Test +import org.junit.runner.RunWith + +/** Unit tests for [TouchUtil] */ +@SmallTest +@RunWith(AndroidJUnit4::class) +class TouchUtilTest { + + @Test + fun isMouseRightClickDownOrMove_onMouseRightButton_returnsTrue() { + val ev = MotionEvent.obtain(200, 300, MotionEvent.ACTION_MOVE, 1.0f, 0.0f, 0) + ev.source = InputDevice.SOURCE_MOUSE + ev.buttonState = MotionEvent.BUTTON_SECONDARY + + assertThat(TouchUtil.isMouseRightClickDownOrMove(ev)).isTrue() + } + + @Test + fun isMouseRightClickDownOrMove_onMouseLeftButton_returnsFalse() { + val ev = MotionEvent.obtain(200, 300, MotionEvent.ACTION_MOVE, 1.0f, 0.0f, 0) + ev.source = InputDevice.SOURCE_MOUSE + ev.buttonState = MotionEvent.BUTTON_PRIMARY + + assertThat(TouchUtil.isMouseRightClickDownOrMove(ev)).isFalse() + } + + @Test + fun isMouseRightClickDownOrMove_onMouseTertiaryButton_returnsFalse() { + val ev = MotionEvent.obtain(200, 300, MotionEvent.ACTION_MOVE, 1.0f, 0.0f, 0) + ev.source = InputDevice.SOURCE_MOUSE + ev.buttonState = MotionEvent.BUTTON_TERTIARY + + assertThat(TouchUtil.isMouseRightClickDownOrMove(ev)).isFalse() + } + + @Test + fun isMouseRightClickDownOrMove_onDpadRightButton_returnsFalse() { + val ev = MotionEvent.obtain(200, 300, MotionEvent.ACTION_MOVE, 1.0f, 0.0f, 0) + ev.source = InputDevice.SOURCE_DPAD + ev.buttonState = MotionEvent.BUTTON_SECONDARY + + assertThat(TouchUtil.isMouseRightClickDownOrMove(ev)).isFalse() + } +}