From e3fbfaca73bcf14cef3465707740cfe45bad8fbf Mon Sep 17 00:00:00 2001 From: Andreas Agvard Date: Mon, 23 Oct 2023 15:30:59 +0200 Subject: [PATCH] Synchonizes touch slop across input consumers This is done so that an outer input consumer isn't inside it's touch slop while an inner consumer has passed it's touch slop. An inner consumer cannot inform the outer consumers that it has intercepted in the current design. Removes MotionEvent.CLASSIFICATION_AMBIGUOUS_GESTURE handling from NavHandleLongPressInputConsumer since other input consumers do not use this mechanism leading to misalligned touch slops. OtherActivityInputConsumer now uses touch slop from the device configuration (it already did so for the squared touch slop). Flag: LEGACY CUSTOM_LPNH_THRESHOLDS DISABLED Bug: 305924072 Test: Manual Change-Id: Idf5e88d75914255923fbbcfb602cf2a53773ff9a --- .../RecentsAnimationDeviceState.java | 31 +++++++++++++++---- .../quickstep/TouchInteractionService.java | 3 +- .../NavHandleLongPressInputConsumer.java | 22 +++++-------- .../OtherActivityInputConsumer.java | 3 +- 4 files changed, 35 insertions(+), 24 deletions(-) diff --git a/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java b/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java index 3fdc7ba7de..8d26fd4a50 100644 --- a/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java +++ b/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java @@ -19,6 +19,7 @@ import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED; import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; import static android.view.Display.DEFAULT_DISPLAY; +import static com.android.launcher3.LauncherPrefs.LONG_PRESS_NAV_HANDLE_SLOP_PERCENTAGE; import static com.android.launcher3.util.DisplayController.CHANGE_ALL; import static com.android.launcher3.util.DisplayController.CHANGE_NAVIGATION_MODE; import static com.android.launcher3.util.DisplayController.CHANGE_ROTATION; @@ -60,6 +61,8 @@ import android.view.ViewConfiguration; import androidx.annotation.BinderThread; import androidx.annotation.NonNull; +import com.android.launcher3.LauncherPrefs; +import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.util.DisplayController; import com.android.launcher3.util.DisplayController.DisplayInfoChangeListener; import com.android.launcher3.util.DisplayController.Info; @@ -86,8 +89,8 @@ public class RecentsAnimationDeviceState implements DisplayInfoChangeListener { static final String SUPPORT_ONE_HANDED_MODE = "ro.support_one_handed_mode"; // TODO: Move to quickstep contract - private static final float QUICKSTEP_TOUCH_SLOP_RATIO_TWO_BUTTON = 9; - private static final float QUICKSTEP_TOUCH_SLOP_RATIO_GESTURAL = 2; + private static final float QUICKSTEP_TOUCH_SLOP_RATIO_TWO_BUTTON = 3f; + private static final float QUICKSTEP_TOUCH_SLOP_RATIO_GESTURAL = 1.414f; private final Context mContext; private final DisplayController mDisplayController; @@ -546,15 +549,31 @@ public class RecentsAnimationDeviceState implements DisplayInfoChangeListener { /** * Returns the touch slop for {@link InputConsumer}s to compare against before pilfering - * pointers. Note that this is squared because it expects to be compared against - * {@link com.android.launcher3.Utilities#squaredHypot} (to avoid square root on each event). + * pointers. */ - public float getSquaredTouchSlop() { + public float getTouchSlop() { float slopMultiplier = isFullyGesturalNavMode() ? QUICKSTEP_TOUCH_SLOP_RATIO_GESTURAL : QUICKSTEP_TOUCH_SLOP_RATIO_TWO_BUTTON; float touchSlop = ViewConfiguration.get(mContext).getScaledTouchSlop(); - return slopMultiplier * touchSlop * touchSlop; + + if (FeatureFlags.CUSTOM_LPNH_THRESHOLDS.get()) { + float customSlopMultiplier = + LauncherPrefs.get(mContext).get(LONG_PRESS_NAV_HANDLE_SLOP_PERCENTAGE) / 100f; + return customSlopMultiplier * slopMultiplier * touchSlop; + } else { + return slopMultiplier * touchSlop; + } + } + + /** + * Returns the squared touch slop for {@link InputConsumer}s to compare against before pilfering + * pointers. Note that this is squared because it expects to be compared against + * {@link com.android.launcher3.Utilities#squaredHypot} (to avoid square root on each event). + */ + public float getSquaredTouchSlop() { + float touchSlop = getTouchSlop(); + return touchSlop * touchSlop; } public String getSystemUiStateString() { diff --git a/quickstep/src/com/android/quickstep/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java index b2f04b89e1..98a9938653 100644 --- a/quickstep/src/com/android/quickstep/TouchInteractionService.java +++ b/quickstep/src/com/android/quickstep/TouchInteractionService.java @@ -963,7 +963,8 @@ public class TouchInteractionService extends Service { .append(SUBSTRING_PREFIX) .append("Long press nav handle enabled, ") .append("using NavHandleLongPressInputConsumer"); - base = new NavHandleLongPressInputConsumer(this, base, mInputMonitorCompat); + base = new NavHandleLongPressInputConsumer(this, base, mInputMonitorCompat, + mDeviceState); } if (mDeviceState.isBubblesExpanded()) { diff --git a/quickstep/src/com/android/quickstep/inputconsumers/NavHandleLongPressInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/NavHandleLongPressInputConsumer.java index f11e537356..32f7bd535c 100644 --- a/quickstep/src/com/android/quickstep/inputconsumers/NavHandleLongPressInputConsumer.java +++ b/quickstep/src/com/android/quickstep/inputconsumers/NavHandleLongPressInputConsumer.java @@ -15,7 +15,6 @@ */ package com.android.quickstep.inputconsumers; -import static com.android.launcher3.LauncherPrefs.LONG_PRESS_NAV_HANDLE_SLOP_PERCENTAGE; import static com.android.launcher3.LauncherPrefs.LONG_PRESS_NAV_HANDLE_TIMEOUT_MS; import static com.android.launcher3.util.Executors.MAIN_EXECUTOR; @@ -28,6 +27,7 @@ import com.android.launcher3.R; import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.util.DisplayController; import com.android.quickstep.InputConsumer; +import com.android.quickstep.RecentsAnimationDeviceState; import com.android.systemui.shared.system.InputMonitorCompat; /** @@ -47,23 +47,18 @@ public class NavHandleLongPressInputConsumer extends DelegateInputConsumer { private MotionEvent mCurrentDownEvent; public NavHandleLongPressInputConsumer(Context context, InputConsumer delegate, - InputMonitorCompat inputMonitor) { + InputMonitorCompat inputMonitor, RecentsAnimationDeviceState deviceState) { super(delegate, inputMonitor); mViewConfiguration = ViewConfiguration.get(context); mNavHandleWidth = context.getResources().getDimensionPixelSize( R.dimen.navigation_home_handle_width); mScreenWidth = DisplayController.INSTANCE.get(context).getInfo().currentSize.x; - float touchSlop; if (FeatureFlags.CUSTOM_LPNH_THRESHOLDS.get()) { - float customSlopMultiplier = - LauncherPrefs.get(context).get(LONG_PRESS_NAV_HANDLE_SLOP_PERCENTAGE) / 100f; - touchSlop = mViewConfiguration.getScaledEdgeSlop() * customSlopMultiplier; mLongPressTimeout = LauncherPrefs.get(context).get(LONG_PRESS_NAV_HANDLE_TIMEOUT_MS); } else { - touchSlop = mViewConfiguration.getScaledTouchSlop(); mLongPressTimeout = ViewConfiguration.getLongPressTimeout(); } - mTouchSlopSquared = touchSlop * touchSlop; + mTouchSlopSquared = deviceState.getSquaredTouchSlop(); mNavHandleLongPressHandler = NavHandleLongPressHandler.newInstance(context); } @@ -87,17 +82,14 @@ public class NavHandleLongPressInputConsumer extends DelegateInputConsumer { } } case MotionEvent.ACTION_MOVE -> { + if (!MAIN_EXECUTOR.getHandler().hasCallbacks(mTriggerLongPress)) { + break; + } + float touchSlopSquared = mTouchSlopSquared; float dx = ev.getX() - mCurrentDownEvent.getX(); float dy = ev.getY() - mCurrentDownEvent.getY(); double distanceSquared = (dx * dx) + (dy * dy); - // If the gesture is ambiguous then require more movement before classifying this - // as a NON long press gesture. - if (ev.getClassification() == MotionEvent.CLASSIFICATION_AMBIGUOUS_GESTURE) { - float ambiguousGestureMultiplier = - mViewConfiguration.getScaledAmbiguousGestureMultiplier(); - touchSlopSquared *= ambiguousGestureMultiplier * ambiguousGestureMultiplier; - } if (distanceSquared > touchSlopSquared) { cancelLongPress(); } diff --git a/quickstep/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java index 28c00eb426..e724547d3e 100644 --- a/quickstep/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java +++ b/quickstep/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java @@ -40,7 +40,6 @@ import android.os.Build; import android.util.Log; import android.view.MotionEvent; import android.view.VelocityTracker; -import android.view.ViewConfiguration; import androidx.annotation.UiThread; @@ -154,7 +153,7 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC boolean continuingPreviousGesture = mTaskAnimationManager.isRecentsAnimationRunning(); mIsDeferredDownTarget = !continuingPreviousGesture && isDeferredDownTarget; - mTouchSlop = ViewConfiguration.get(this).getScaledTouchSlop(); + mTouchSlop = mDeviceState.getTouchSlop(); mSquaredTouchSlop = mDeviceState.getSquaredTouchSlop(); mPassedPilferInputSlop = mPassedWindowMoveSlop = continuingPreviousGesture;