Merge "Support 4-finger gesture to quick switch" into udc-dev

This commit is contained in:
Tracy Zhou
2023-04-25 18:21:37 +00:00
committed by Android (Google) Code Review
7 changed files with 101 additions and 28 deletions

View File

@@ -15,11 +15,15 @@
*/
package com.android.launcher3.uioverrides.touchcontrollers;
import static android.view.MotionEvent.ACTION_DOWN;
import static android.view.MotionEvent.ACTION_MOVE;
import static com.android.launcher3.LauncherAnimUtils.newCancelListener;
import static com.android.launcher3.LauncherState.NORMAL;
import static com.android.launcher3.LauncherState.OVERVIEW;
import static com.android.launcher3.LauncherState.OVERVIEW_ACTIONS;
import static com.android.launcher3.LauncherState.QUICK_SWITCH_FROM_HOME;
import static com.android.launcher3.MotionEventsUtils.isTrackpadFourFingerSwipe;
import static com.android.launcher3.MotionEventsUtils.isTrackpadMultiFingerSwipe;
import static com.android.launcher3.anim.AlphaUpdateListener.ALPHA_CUTOFF_THRESHOLD;
import static com.android.launcher3.anim.AnimatorListeners.forEndCallback;
@@ -106,6 +110,7 @@ public class NoButtonQuickSwitchTouchController implements TouchController,
newCancelListener(this::clearState);
private boolean mNoIntercept;
private Boolean mIsTrackpadFourFingerSwipe;
private LauncherState mStartState;
private boolean mIsHomeScreenVisible = true;
@@ -131,7 +136,9 @@ public class NoButtonQuickSwitchTouchController implements TouchController,
@Override
public boolean onControllerInterceptTouchEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
int action = ev.getActionMasked();
if (action == ACTION_DOWN) {
mIsTrackpadFourFingerSwipe = null;
mNoIntercept = !canInterceptTouch(ev);
if (mNoIntercept) {
return false;
@@ -140,6 +147,13 @@ public class NoButtonQuickSwitchTouchController implements TouchController,
// Only detect horizontal swipe for intercept, then we will allow swipe up as well.
mSwipeDetector.setDetectableScrollConditions(DIRECTION_RIGHT,
false /* ignoreSlopWhenSettling */);
} else if (isTrackpadMultiFingerSwipe(ev) && mIsTrackpadFourFingerSwipe == null
&& action == ACTION_MOVE) {
mIsTrackpadFourFingerSwipe = isTrackpadFourFingerSwipe(ev);
mNoIntercept = !mIsTrackpadFourFingerSwipe;
if (mNoIntercept) {
return false;
}
}
if (mNoIntercept) {
@@ -162,9 +176,6 @@ public class NoButtonQuickSwitchTouchController implements TouchController,
if ((ev.getEdgeFlags() & Utilities.EDGE_NAV_BAR) == 0) {
return false;
}
if (isTrackpadMultiFingerSwipe(ev)) {
return false;
}
int stateFlags = SystemUiProxy.INSTANCE.get(mLauncher).getLastSystemUiStateFlags();
if ((stateFlags & SYSUI_STATE_OVERVIEW_DISABLED) != 0) {
return false;

View File

@@ -2064,8 +2064,8 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>,
mRecentsView.setRecentsAnimationTargets(mRecentsAnimationController,
mRecentsAnimationTargets));
// Disable scrolling in RecentsView for trackpad gestures.
if (!mGestureState.isTrackpadGesture()) {
// Disable scrolling in RecentsView for trackpad 3-finger swipe up gesture.
if (!mGestureState.isThreeFingerTrackpadGesture()) {
mRecentsViewScrollLinked = true;
}
}

View File

@@ -15,6 +15,9 @@
*/
package com.android.quickstep;
import static com.android.launcher3.MotionEventsUtils.isTrackpadFourFingerSwipe;
import static com.android.launcher3.MotionEventsUtils.isTrackpadMultiFingerSwipe;
import static com.android.launcher3.MotionEventsUtils.isTrackpadThreeFingerSwipe;
import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_BACKGROUND;
import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_HOME;
import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_OVERVIEW;
@@ -27,6 +30,7 @@ import android.annotation.Nullable;
import android.annotation.TargetApi;
import android.content.Intent;
import android.os.Build;
import android.view.MotionEvent;
import android.view.RemoteAnimationTarget;
import com.android.launcher3.statemanager.BaseState;
@@ -139,8 +143,30 @@ public class GestureState implements RecentsAnimationCallbacks.RecentsAnimationL
private final BaseActivityInterface mActivityInterface;
private final MultiStateCallback mStateCallback;
private final int mGestureId;
private boolean mIsTrackpadGesture;
public enum TrackpadGestureType {
NONE,
// Assigned before we know whether it's a 3-finger or 4-finger gesture.
MULTI_FINGER,
THREE_FINGER,
FOUR_FINGER;
public static TrackpadGestureType getTrackpadGestureType(MotionEvent event) {
if (!isTrackpadMultiFingerSwipe(event)) {
return TrackpadGestureType.NONE;
}
if (isTrackpadThreeFingerSwipe(event)) {
return TrackpadGestureType.THREE_FINGER;
}
if (isTrackpadFourFingerSwipe(event)) {
return TrackpadGestureType.FOUR_FINGER;
}
return TrackpadGestureType.MULTI_FINGER;
}
}
private TrackpadGestureType mTrackpadGestureType = TrackpadGestureType.NONE;
private CachedTaskInfo mRunningTask;
private GestureEndTarget mEndTarget;
private RemoteAnimationTarget mLastAppearedTaskTarget;
@@ -249,17 +275,22 @@ public class GestureState implements RecentsAnimationCallbacks.RecentsAnimationL
}
/**
* Sets if the gesture is is from the trackpad.
* Sets if the gesture is is from the trackpad, if so, whether 3-finger, or 4-finger
*/
public void setIsTrackpadGesture(boolean isTrackpadGesture) {
mIsTrackpadGesture = isTrackpadGesture;
public void setTrackpadGestureType(TrackpadGestureType trackpadGestureType) {
mTrackpadGestureType = trackpadGestureType;
}
/**
* @return if the gesture is from the trackpad.
*/
public boolean isTrackpadGesture() {
return mIsTrackpadGesture;
return mTrackpadGestureType != TrackpadGestureType.NONE;
}
public boolean isThreeFingerTrackpadGesture() {
return mTrackpadGestureType == TrackpadGestureType.THREE_FINGER;
}
public boolean isFourFingerTrackpadGesture() {
return mTrackpadGestureType == TrackpadGestureType.FOUR_FINGER;
}
/**

View File

@@ -249,7 +249,7 @@ public class OverviewCommandHelper {
}
GestureState gestureState = mService.createGestureState(GestureState.DEFAULT_STATE,
false /* isTrackpadGesture */);
GestureState.TrackpadGestureType.NONE);
gestureState.setHandlingAtomicEvent(true);
AbsSwipeUpHandler interactionHandler = mService.getSwipeUpHandlerFactory()
.newHandler(gestureState, cmd.createTime);

View File

@@ -24,11 +24,11 @@ import static android.view.MotionEvent.ACTION_POINTER_UP;
import static android.view.MotionEvent.ACTION_UP;
import static com.android.launcher3.Launcher.INTENT_ACTION_ALL_APPS_TOGGLE;
import static com.android.launcher3.MotionEventsUtils.isTrackpadMultiFingerSwipe;
import static com.android.launcher3.config.FeatureFlags.ASSISTANT_GIVES_LAUNCHER_FOCUS;
import static com.android.launcher3.config.FeatureFlags.ENABLE_TRACKPAD_GESTURE;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import static com.android.quickstep.GestureState.DEFAULT_STATE;
import static com.android.quickstep.GestureState.TrackpadGestureType.getTrackpadGestureType;
import static com.android.quickstep.util.ActiveGestureErrorDetector.GestureEvent.FLAG_USING_OTHER_ACTIVITY_INPUT_CONSUMER;
import static com.android.quickstep.util.ActiveGestureErrorDetector.GestureEvent.MOTION_DOWN;
import static com.android.quickstep.util.ActiveGestureErrorDetector.GestureEvent.MOTION_MOVE;
@@ -647,7 +647,7 @@ public class TouchInteractionService extends Service
// onConsumerInactive and wipe the previous gesture state
GestureState prevGestureState = new GestureState(mGestureState);
GestureState newGestureState = createGestureState(mGestureState,
isTrackpadMultiFingerSwipe(event));
getTrackpadGestureType(event));
newGestureState.setSwipeUpStartTimeMs(SystemClock.uptimeMillis());
mConsumer.onConsumerAboutToBeSwitched();
mGestureState = newGestureState;
@@ -656,7 +656,7 @@ public class TouchInteractionService extends Service
} else if (mDeviceState.isUserUnlocked() && mDeviceState.isFullyGesturalNavMode()
&& mDeviceState.canTriggerAssistantAction(event)) {
mGestureState = createGestureState(mGestureState,
isTrackpadMultiFingerSwipe(event));
getTrackpadGestureType(event));
// Do not change mConsumer as if there is an ongoing QuickSwitch gesture, we
// should not interrupt it. QuickSwitch assumes that interruption can only
// happen if the next gesture is also quick switch.
@@ -713,9 +713,13 @@ public class TouchInteractionService extends Service
event.setAction(ACTION_CANCEL);
}
// Skip ACTION_POINTER_DOWN and ACTION_POINTER_UP events from trackpad.
if (!mGestureState.isTrackpadGesture() || (action != ACTION_POINTER_DOWN
&& action != ACTION_POINTER_UP)) {
if (mGestureState.isTrackpadGesture() && (action == ACTION_POINTER_DOWN
|| action == ACTION_POINTER_UP)) {
// Skip ACTION_POINTER_DOWN and ACTION_POINTER_UP events from trackpad.
if (action == ACTION_POINTER_DOWN) {
mGestureState.setTrackpadGestureType(getTrackpadGestureType(event));
}
} else {
mUncheckedConsumer.onMotionEvent(event);
}
@@ -749,7 +753,7 @@ public class TouchInteractionService extends Service
}
public GestureState createGestureState(GestureState previousGestureState,
boolean isTrackpadGesture) {
GestureState.TrackpadGestureType trackpadGestureType) {
final GestureState gestureState;
TopTaskTracker.CachedTaskInfo taskInfo;
if (mTaskAnimationManager.isRecentsAnimationRunning()) {
@@ -766,7 +770,7 @@ public class TouchInteractionService extends Service
taskInfo = TopTaskTracker.INSTANCE.get(this).getCachedTopTask(false);
gestureState.updateRunningTask(taskInfo);
}
gestureState.setIsTrackpadGesture(isTrackpadGesture);
gestureState.setTrackpadGestureType(trackpadGestureType);
// Log initial state for the gesture.
ActiveGestureLog.INSTANCE.addLog(new CompoundString("Current running task package name=")

View File

@@ -203,8 +203,24 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC
}
int edgeFlags = ev.getEdgeFlags();
ev.setEdgeFlags(edgeFlags | EDGE_NAV_BAR);
// Disable scrolling in RecentsView for trackpad gestures.
if (!mGestureState.isTrackpadGesture()) {
if (mGestureState.isTrackpadGesture()) {
// Disable scrolling in RecentsView for 3-finger trackpad gesture. We don't know if a
// trackpad motion event is 3-finger or 4-finger with the U API until ACTION_MOVE (we
// skip ACTION_POINTER_UP events in TouchInteractionService), so in order to make sure
// that RecentsView always get a closed sequence of motion events and yet disable
// 3-finger scroll, we do the following (1) always dispatch ACTION_DOWN and ACTION_UP
// trackpad multi-finger motion events. (2) only dispatch 4-finger ACTION_MOVE motion
// events.
switch (ev.getActionMasked()) {
case ACTION_MOVE -> {
if (mGestureState.isFourFingerTrackpadGesture()) {
mRecentsViewDispatcher.dispatchEvent(ev);
}
}
default -> mRecentsViewDispatcher.dispatchEvent(ev);
}
} else {
mRecentsViewDispatcher.dispatchEvent(ev);
}
ev.setEdgeFlags(edgeFlags);
@@ -312,9 +328,12 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC
// Do not allow quick switch for trackpad 3-finger gestures
// TODO(b/261815244): might need to impose stronger conditions for the swipe
// angle
boolean noQuickSwitchForTrackpadGesture = mGestureState.isTrackpadGesture()
&& isLikelyToStartNewTask;
if (isHorizontalSwipeWhenDisabled || noQuickSwitchForTrackpadGesture) {
boolean noQuickSwitchForThreeFingerGesture = isLikelyToStartNewTask
&& mGestureState.isThreeFingerTrackpadGesture();
boolean noQuickstepForFourFingerGesture = !isLikelyToStartNewTask
&& mGestureState.isFourFingerTrackpadGesture();
if (isHorizontalSwipeWhenDisabled || noQuickSwitchForThreeFingerGesture
|| noQuickstepForFourFingerGesture) {
forceCancelGesture(ev);
break;
}

View File

@@ -42,6 +42,14 @@ public class MotionEventsUtils {
&& event.getClassification() == CLASSIFICATION_MULTI_FINGER_SWIPE;
}
public static boolean isTrackpadThreeFingerSwipe(MotionEvent event) {
return isTrackpadMultiFingerSwipe(event) && event.getPointerCount() == 3;
}
public static boolean isTrackpadFourFingerSwipe(MotionEvent event) {
return isTrackpadMultiFingerSwipe(event) && event.getPointerCount() == 4;
}
public static boolean isTrackpadMotionEvent(MotionEvent event) {
return isTrackpadScroll(event) || isTrackpadMultiFingerSwipe(event);
}