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
This commit is contained in:
Andreas Agvard
2023-10-23 15:30:59 +02:00
parent 4d59d52d1e
commit e3fbfaca73
4 changed files with 35 additions and 24 deletions

View File

@@ -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() {

View File

@@ -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()) {

View File

@@ -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();
}

View File

@@ -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;