Adding horizontal swipe support for 3p launcher
Bug: 137197916 Change-Id: I0fb5db791b3471d651db43f0e8c30b8d5baf9f27
This commit is contained in:
@@ -18,26 +18,41 @@ package com.android.quickstep;
|
||||
import static android.os.VibrationEffect.EFFECT_CLICK;
|
||||
import static android.os.VibrationEffect.createPredefined;
|
||||
|
||||
import static com.android.launcher3.Utilities.postAsyncCallback;
|
||||
import static com.android.launcher3.anim.Interpolators.DEACCEL;
|
||||
import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
|
||||
import static com.android.quickstep.TouchInteractionService.BACKGROUND_EXECUTOR;
|
||||
import static com.android.quickstep.TouchInteractionService.MAIN_THREAD_EXECUTOR;
|
||||
import static com.android.quickstep.TouchInteractionService.TOUCH_INTERACTION_LOG;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.ActivityManager.RunningTaskInfo;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.PointF;
|
||||
import android.os.Build;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.os.VibrationEffect;
|
||||
import android.os.Vibrator;
|
||||
import android.provider.Settings;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.animation.Interpolator;
|
||||
|
||||
import com.android.launcher3.BaseDraggingActivity;
|
||||
import com.android.launcher3.DeviceProfile;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.graphics.RotationMode;
|
||||
import com.android.quickstep.ActivityControlHelper.ActivityInitListener;
|
||||
import com.android.quickstep.inputconsumers.InputConsumer;
|
||||
import com.android.quickstep.util.ClipAnimationHelper;
|
||||
import com.android.quickstep.util.ClipAnimationHelper.TransformParams;
|
||||
import com.android.quickstep.util.SwipeAnimationTargetSet.SwipeAnimationListener;
|
||||
import com.android.quickstep.views.RecentsView;
|
||||
import com.android.quickstep.views.TaskView;
|
||||
import com.android.systemui.shared.system.InputConsumerController;
|
||||
import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
@@ -47,7 +62,10 @@ import androidx.annotation.UiThread;
|
||||
* Base class for swipe up handler with some utility methods
|
||||
*/
|
||||
@TargetApi(Build.VERSION_CODES.Q)
|
||||
public abstract class BaseSwipeUpHandler implements SwipeAnimationListener {
|
||||
public abstract class BaseSwipeUpHandler<T extends BaseDraggingActivity>
|
||||
implements SwipeAnimationListener {
|
||||
|
||||
private static final String TAG = "BaseSwipeUpHandler";
|
||||
|
||||
// Start resisting when swiping past this factor of mTransitionDragLength.
|
||||
private static final float DRAG_LENGTH_FACTOR_START_PULLBACK = 1.4f;
|
||||
@@ -61,6 +79,9 @@ public abstract class BaseSwipeUpHandler implements SwipeAnimationListener {
|
||||
protected float mDragLengthFactor = 1;
|
||||
|
||||
protected final Context mContext;
|
||||
protected final OverviewComponentObserver mOverviewComponentObserver;
|
||||
protected final ActivityControlHelper<T> mActivityControlHelper;
|
||||
protected final RecentsModel mRecentsModel;
|
||||
|
||||
protected final ClipAnimationHelper mClipAnimationHelper;
|
||||
protected final TransformParams mTransformParams = new TransformParams();
|
||||
@@ -73,18 +94,48 @@ public abstract class BaseSwipeUpHandler implements SwipeAnimationListener {
|
||||
// visible.
|
||||
protected final AnimatedFloat mCurrentShift = new AnimatedFloat(this::updateFinalShift);
|
||||
|
||||
protected final ActivityInitListener mActivityInitListener;
|
||||
protected final RecentsAnimationWrapper mRecentsAnimationWrapper;
|
||||
|
||||
protected T mActivity;
|
||||
protected RecentsView mRecentsView;
|
||||
protected DeviceProfile mDp;
|
||||
private final int mPageSpacing;
|
||||
|
||||
protected Runnable mGestureEndCallback;
|
||||
|
||||
protected BaseSwipeUpHandler(Context context) {
|
||||
mContext = context;
|
||||
mClipAnimationHelper = new ClipAnimationHelper(context);
|
||||
protected final Handler mMainThreadHandler = MAIN_THREAD_EXECUTOR.getHandler();
|
||||
protected MultiStateCallback mStateCallback;
|
||||
|
||||
protected boolean mCanceled;
|
||||
protected int mFinishingRecentsAnimationForNewTaskId = -1;
|
||||
|
||||
protected BaseSwipeUpHandler(Context context,
|
||||
OverviewComponentObserver overviewComponentObserver,
|
||||
RecentsModel recentsModel, InputConsumerController inputConsumer) {
|
||||
mContext = context;
|
||||
mOverviewComponentObserver = overviewComponentObserver;
|
||||
mActivityControlHelper = overviewComponentObserver.getActivityControlHelper();
|
||||
mRecentsModel = recentsModel;
|
||||
mActivityInitListener =
|
||||
mActivityControlHelper.createActivityInitListener(this::onActivityInit);
|
||||
mRecentsAnimationWrapper = new RecentsAnimationWrapper(inputConsumer,
|
||||
this::createNewInputProxyHandler);
|
||||
|
||||
mClipAnimationHelper = new ClipAnimationHelper(context);
|
||||
mPageSpacing = context.getResources().getDimensionPixelSize(R.dimen.recents_page_spacing);
|
||||
mVibrator = context.getSystemService(Vibrator.class);
|
||||
}
|
||||
|
||||
public void performHapticFeedback() {
|
||||
protected void setStateOnUiThread(int stateFlag) {
|
||||
if (Looper.myLooper() == mMainThreadHandler.getLooper()) {
|
||||
mStateCallback.setState(stateFlag);
|
||||
} else {
|
||||
postAsyncCallback(mMainThreadHandler, () -> mStateCallback.setState(stateFlag));
|
||||
}
|
||||
}
|
||||
|
||||
protected void performHapticFeedback() {
|
||||
if (!mVibrator.hasVibrator()) {
|
||||
return;
|
||||
}
|
||||
@@ -130,12 +181,76 @@ public abstract class BaseSwipeUpHandler implements SwipeAnimationListener {
|
||||
mGestureEndCallback = gestureEndCallback;
|
||||
}
|
||||
|
||||
public abstract Intent getLaunchIntent();
|
||||
|
||||
protected void linkRecentsViewScroll() {
|
||||
SyncRtSurfaceTransactionApplierCompat.create(mRecentsView, applier -> {
|
||||
mTransformParams.setSyncTransactionApplier(applier);
|
||||
mRecentsAnimationWrapper.runOnInit(() ->
|
||||
mRecentsAnimationWrapper.targetSet.addDependentTransactionApplier(applier));
|
||||
});
|
||||
|
||||
mRecentsView.setOnScrollChangeListener((v, scrollX, scrollY, oldScrollX, oldScrollY) -> {
|
||||
if (moveWindowWithRecentsScroll()) {
|
||||
updateFinalShift();
|
||||
}
|
||||
});
|
||||
mRecentsView.setRecentsAnimationWrapper(mRecentsAnimationWrapper);
|
||||
mRecentsView.setClipAnimationHelper(mClipAnimationHelper);
|
||||
}
|
||||
|
||||
protected void startNewTask(int successStateFlag, Consumer<Boolean> resultCallback) {
|
||||
// Launch the task user scrolled to (mRecentsView.getNextPage()).
|
||||
if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
|
||||
// We finish recents animation inside launchTask() when live tile is enabled.
|
||||
mRecentsView.getTaskViewAt(mRecentsView.getNextPage()).launchTask(false /* animate */,
|
||||
true /* freezeTaskList */);
|
||||
} else {
|
||||
int taskId = mRecentsView.getTaskViewAt(mRecentsView.getNextPage()).getTask().key.id;
|
||||
mFinishingRecentsAnimationForNewTaskId = taskId;
|
||||
mRecentsAnimationWrapper.finish(true /* toRecents */, () -> {
|
||||
if (!mCanceled) {
|
||||
TaskView nextTask = mRecentsView.getTaskView(taskId);
|
||||
if (nextTask != null) {
|
||||
nextTask.launchTask(false /* animate */, true /* freezeTaskList */,
|
||||
success -> {
|
||||
resultCallback.accept(success);
|
||||
if (!success) {
|
||||
mActivityControlHelper.onLaunchTaskFailed(mActivity);
|
||||
nextTask.notifyTaskLaunchFailed(TAG);
|
||||
} else {
|
||||
mActivityControlHelper.onLaunchTaskSuccess(mActivity);
|
||||
}
|
||||
}, mMainThreadHandler);
|
||||
}
|
||||
setStateOnUiThread(successStateFlag);
|
||||
}
|
||||
mCanceled = false;
|
||||
mFinishingRecentsAnimationForNewTaskId = -1;
|
||||
});
|
||||
}
|
||||
TOUCH_INTERACTION_LOG.addLog("finishRecentsAnimation", true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the window should be translated horizontally if the recents view scrolls
|
||||
*/
|
||||
protected abstract boolean moveWindowWithRecentsScroll();
|
||||
|
||||
protected abstract boolean onActivityInit(final T activity, Boolean alreadyOnHome);
|
||||
|
||||
/**
|
||||
* Called to create a input proxy for the running task
|
||||
*/
|
||||
@UiThread
|
||||
protected abstract InputConsumer createNewInputProxyHandler();
|
||||
|
||||
/**
|
||||
* Called when the value of {@link #mCurrentShift} changes
|
||||
*/
|
||||
@UiThread
|
||||
public abstract void updateFinalShift();
|
||||
|
||||
|
||||
/**
|
||||
* Called when motion pause is detected
|
||||
*/
|
||||
@@ -150,15 +265,39 @@ public abstract class BaseSwipeUpHandler implements SwipeAnimationListener {
|
||||
@UiThread
|
||||
public abstract void onGestureEnded(float endVelocity, PointF velocity, PointF downPos);
|
||||
|
||||
public void onConsumerAboutToBeSwitched(SwipeSharedState sharedState) { }
|
||||
public abstract void onConsumerAboutToBeSwitched(SwipeSharedState sharedState);
|
||||
|
||||
public void setIsLikelyToStartNewTask(boolean isLikelyToStartNewTask) { }
|
||||
|
||||
public void initWhenReady() { }
|
||||
public void initWhenReady() {
|
||||
// Preload the plan
|
||||
mRecentsModel.getTasks(null);
|
||||
|
||||
mActivityInitListener.register();
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the transform on the recents animation without any additional null checks
|
||||
*/
|
||||
protected void applyTransformUnchecked() {
|
||||
float shift = mCurrentShift.value;
|
||||
float offsetX = mRecentsView == null ? 0 : mRecentsView.getScrollOffset();
|
||||
float offsetScale = getTaskCurveScaleForOffsetX(offsetX,
|
||||
mClipAnimationHelper.getTargetRect().width());
|
||||
mTransformParams.setProgress(shift).setOffsetX(offsetX).setOffsetScale(offsetScale);
|
||||
mClipAnimationHelper.applyTransform(mRecentsAnimationWrapper.targetSet,
|
||||
mTransformParams);
|
||||
}
|
||||
|
||||
private float getTaskCurveScaleForOffsetX(float offsetX, float taskWidth) {
|
||||
float distanceToReachEdge = mDp.widthPx / 2 + taskWidth / 2 + mPageSpacing;
|
||||
float interpolation = Math.min(1, offsetX / distanceToReachEdge);
|
||||
return TaskView.getCurveScaleForInterpolation(interpolation);
|
||||
}
|
||||
|
||||
public interface Factory {
|
||||
|
||||
BaseSwipeUpHandler newHandler(RunningTaskInfo runningTask,
|
||||
long touchTimeMs, boolean continuingLastGesture);
|
||||
long touchTimeMs, boolean continuingLastGesture, boolean isLikelyToStartNewTask);
|
||||
}
|
||||
}
|
||||
|
||||
+8
-12
@@ -649,20 +649,17 @@ public class TouchInteractionService extends Service implements
|
||||
|
||||
final boolean shouldDefer;
|
||||
final BaseSwipeUpHandler.Factory factory;
|
||||
final Intent homeIntent;
|
||||
|
||||
if (mMode == Mode.NO_BUTTON && !mOverviewComponentObserver.isHomeAndOverviewSame()) {
|
||||
shouldDefer = true;
|
||||
shouldDefer = !sSwipeSharedState.recentsAnimationFinishInterrupted;
|
||||
factory = mFallbackNoButtonFactory;
|
||||
homeIntent = mOverviewComponentObserver.getHomeIntent();
|
||||
} else {
|
||||
shouldDefer = mOverviewComponentObserver.getActivityControlHelper()
|
||||
.deferStartingActivity(mActiveNavBarRegion, event);
|
||||
factory = mWindowTreansformFactory;
|
||||
homeIntent = mOverviewComponentObserver.getOverviewIntent();
|
||||
}
|
||||
|
||||
return new OtherActivityInputConsumer(this, runningTaskInfo, homeIntent,
|
||||
return new OtherActivityInputConsumer(this, runningTaskInfo,
|
||||
shouldDefer, mOverviewCallbacks, this::onConsumerInactive,
|
||||
sSwipeSharedState, mInputMonitorCompat, mSwipeTouchRegion,
|
||||
disableHorizontalSwipe(event), factory);
|
||||
@@ -809,16 +806,15 @@ public class TouchInteractionService extends Service implements
|
||||
}
|
||||
|
||||
private BaseSwipeUpHandler createWindowTransformSwipeHandler(RunningTaskInfo runningTask,
|
||||
long touchTimeMs, boolean continuingLastGesture) {
|
||||
return new WindowTransformSwipeHandler(
|
||||
runningTask, this, touchTimeMs,
|
||||
mOverviewComponentObserver.getActivityControlHelper(),
|
||||
continuingLastGesture, mInputConsumer, mRecentsModel);
|
||||
long touchTimeMs, boolean continuingLastGesture, boolean isLikelyToStartNewTask) {
|
||||
return new WindowTransformSwipeHandler(runningTask, this, touchTimeMs,
|
||||
mOverviewComponentObserver, continuingLastGesture, mInputConsumer, mRecentsModel);
|
||||
}
|
||||
|
||||
private BaseSwipeUpHandler createFallbackNoButtonSwipeHandler(RunningTaskInfo runningTask,
|
||||
long touchTimeMs, boolean continuingLastGesture) {
|
||||
return new FallbackNoButtonInputConsumer(this, mOverviewComponentObserver, runningTask);
|
||||
long touchTimeMs, boolean continuingLastGesture, boolean isLikelyToStartNewTask) {
|
||||
return new FallbackNoButtonInputConsumer(this, mOverviewComponentObserver, runningTask,
|
||||
mRecentsModel, mInputConsumer, isLikelyToStartNewTask, continuingLastGesture);
|
||||
}
|
||||
|
||||
public static void startRecentsActivityAsync(Intent intent, RecentsAnimationListener listener) {
|
||||
|
||||
+32
-103
@@ -18,7 +18,6 @@ package com.android.quickstep;
|
||||
import static com.android.launcher3.BaseActivity.INVISIBLE_BY_STATE_HANDLER;
|
||||
import static com.android.launcher3.BaseActivity.STATE_HANDLER_INVISIBILITY_FLAGS;
|
||||
import static com.android.launcher3.Utilities.SINGLE_FRAME_MS;
|
||||
import static com.android.launcher3.Utilities.postAsyncCallback;
|
||||
import static com.android.launcher3.anim.Interpolators.ACCEL_1_5;
|
||||
import static com.android.launcher3.anim.Interpolators.DEACCEL;
|
||||
import static com.android.launcher3.anim.Interpolators.LINEAR;
|
||||
@@ -32,7 +31,6 @@ import static com.android.launcher3.views.FloatingIconView.SHAPE_PROGRESS_DURATI
|
||||
import static com.android.quickstep.ActivityControlHelper.AnimationFactory.ShelfAnimState.HIDE;
|
||||
import static com.android.quickstep.ActivityControlHelper.AnimationFactory.ShelfAnimState.PEEK;
|
||||
import static com.android.quickstep.MultiStateCallback.DEBUG_STATES;
|
||||
import static com.android.quickstep.TouchInteractionService.MAIN_THREAD_EXECUTOR;
|
||||
import static com.android.quickstep.TouchInteractionService.TOUCH_INTERACTION_LOG;
|
||||
import static com.android.quickstep.WindowTransformSwipeHandler.GestureEndTarget.HOME;
|
||||
import static com.android.quickstep.WindowTransformSwipeHandler.GestureEndTarget.LAST_TASK;
|
||||
@@ -48,14 +46,13 @@ import android.animation.ValueAnimator;
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.ActivityManager.RunningTaskInfo;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Point;
|
||||
import android.graphics.PointF;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
import android.os.Build;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.os.SystemClock;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
@@ -82,7 +79,6 @@ import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
|
||||
import com.android.launcher3.util.RaceConditionTracker;
|
||||
import com.android.launcher3.util.TraceHelper;
|
||||
import com.android.launcher3.views.FloatingIconView;
|
||||
import com.android.quickstep.ActivityControlHelper.ActivityInitListener;
|
||||
import com.android.quickstep.ActivityControlHelper.AnimationFactory;
|
||||
import com.android.quickstep.ActivityControlHelper.AnimationFactory.ShelfAnimState;
|
||||
import com.android.quickstep.ActivityControlHelper.HomeAnimationFactory;
|
||||
@@ -99,14 +95,14 @@ import com.android.systemui.shared.recents.model.ThumbnailData;
|
||||
import com.android.systemui.shared.system.InputConsumerController;
|
||||
import com.android.systemui.shared.system.LatencyTrackerCompat;
|
||||
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
|
||||
import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat;
|
||||
import com.android.systemui.shared.system.WindowCallbacksCompat;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.UiThread;
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.O)
|
||||
public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> extends BaseSwipeUpHandler
|
||||
public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
|
||||
extends BaseSwipeUpHandler<T>
|
||||
implements OnApplyWindowInsetsListener {
|
||||
private static final String TAG = WindowTransformSwipeHandler.class.getSimpleName();
|
||||
|
||||
@@ -219,35 +215,24 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> extends
|
||||
// Either RectFSpringAnim (if animating home) or ObjectAnimator (from mCurrentShift) otherwise
|
||||
private RunningWindowAnim mRunningWindowAnim;
|
||||
private boolean mIsShelfPeeking;
|
||||
private DeviceProfile mDp;
|
||||
|
||||
private boolean mContinuingLastGesture;
|
||||
// To avoid UI jump when gesture is started, we offset the animation by the threshold.
|
||||
private float mShiftAtGestureStart = 0;
|
||||
|
||||
private final Handler mMainThreadHandler = MAIN_THREAD_EXECUTOR.getHandler();
|
||||
|
||||
private final ActivityControlHelper<T> mActivityControlHelper;
|
||||
private final ActivityInitListener mActivityInitListener;
|
||||
private final RecentsModel mRecentsModel;
|
||||
|
||||
private final SysUINavigationMode.Mode mMode;
|
||||
private final Mode mMode;
|
||||
|
||||
private final int mRunningTaskId;
|
||||
private ThumbnailData mTaskSnapshot;
|
||||
|
||||
private MultiStateCallback mStateCallback;
|
||||
// Used to control launcher components throughout the swipe gesture.
|
||||
private AnimatorPlaybackController mLauncherTransitionController;
|
||||
private boolean mHasLauncherTransitionControllerStarted;
|
||||
|
||||
private T mActivity;
|
||||
private AnimationFactory mAnimationFactory = (t) -> { };
|
||||
private LiveTileOverlay mLiveTileOverlay = new LiveTileOverlay();
|
||||
|
||||
private boolean mCanceled;
|
||||
private boolean mWasLauncherAlreadyVisible;
|
||||
private int mFinishingRecentsAnimationForNewTaskId = -1;
|
||||
|
||||
private boolean mPassedOverviewThreshold;
|
||||
private boolean mGestureStarted;
|
||||
@@ -256,24 +241,17 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> extends
|
||||
private PointF mDownPos;
|
||||
private boolean mIsLikelyToStartNewTask;
|
||||
|
||||
private final RecentsAnimationWrapper mRecentsAnimationWrapper;
|
||||
|
||||
private final long mTouchTimeMs;
|
||||
private long mLauncherFrameDrawnTime;
|
||||
|
||||
public WindowTransformSwipeHandler(RunningTaskInfo runningTaskInfo, Context context,
|
||||
long touchTimeMs, ActivityControlHelper<T> controller, boolean continuingLastGesture,
|
||||
long touchTimeMs, OverviewComponentObserver overviewComponentObserver,
|
||||
boolean continuingLastGesture,
|
||||
InputConsumerController inputConsumer, RecentsModel recentsModel) {
|
||||
super(context);
|
||||
super(context, overviewComponentObserver, recentsModel, inputConsumer);
|
||||
mRunningTaskId = runningTaskInfo.id;
|
||||
mTouchTimeMs = touchTimeMs;
|
||||
mActivityControlHelper = controller;
|
||||
mRecentsModel = recentsModel;
|
||||
mActivityInitListener = mActivityControlHelper
|
||||
.createActivityInitListener(this::onActivityInit);
|
||||
mContinuingLastGesture = continuingLastGesture;
|
||||
mRecentsAnimationWrapper = new RecentsAnimationWrapper(inputConsumer,
|
||||
this::createNewInputProxyHandler);
|
||||
|
||||
mMode = SysUINavigationMode.getMode(context);
|
||||
initStateCallbacks();
|
||||
@@ -342,14 +320,6 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> extends
|
||||
}
|
||||
}
|
||||
|
||||
private void setStateOnUiThread(int stateFlag) {
|
||||
if (Looper.myLooper() == mMainThreadHandler.getLooper()) {
|
||||
mStateCallback.setState(stateFlag);
|
||||
} else {
|
||||
postAsyncCallback(mMainThreadHandler, () -> mStateCallback.setState(stateFlag));
|
||||
}
|
||||
}
|
||||
|
||||
private Rect getStackBounds(DeviceProfile dp) {
|
||||
if (mActivity != null) {
|
||||
int loc[] = new int[2];
|
||||
@@ -383,14 +353,7 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> extends
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initWhenReady() {
|
||||
// Preload the plan
|
||||
mRecentsModel.getTasks(null);
|
||||
|
||||
mActivityInitListener.register();
|
||||
}
|
||||
|
||||
private boolean onActivityInit(final T activity, Boolean alreadyOnHome) {
|
||||
protected boolean onActivityInit(final T activity, Boolean alreadyOnHome) {
|
||||
if (mActivity == activity) {
|
||||
return true;
|
||||
}
|
||||
@@ -411,19 +374,7 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> extends
|
||||
}
|
||||
|
||||
mRecentsView = activity.getOverviewPanel();
|
||||
SyncRtSurfaceTransactionApplierCompat.create(mRecentsView, applier -> {
|
||||
mTransformParams.setSyncTransactionApplier(applier);
|
||||
mRecentsAnimationWrapper.runOnInit(() ->
|
||||
mRecentsAnimationWrapper.targetSet.addDependentTransactionApplier(applier));
|
||||
});
|
||||
|
||||
mRecentsView.setOnScrollChangeListener((v, scrollX, scrollY, oldScrollX, oldScrollY) -> {
|
||||
if (mGestureEndTarget != HOME) {
|
||||
updateFinalShift();
|
||||
}
|
||||
});
|
||||
mRecentsView.setRecentsAnimationWrapper(mRecentsAnimationWrapper);
|
||||
mRecentsView.setClipAnimationHelper(mClipAnimationHelper);
|
||||
linkRecentsViewScroll();
|
||||
mRecentsView.setLiveTileOverlay(mLiveTileOverlay);
|
||||
mActivity.getRootView().getOverlay().add(mLiveTileOverlay);
|
||||
|
||||
@@ -438,6 +389,11 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> extends
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean moveWindowWithRecentsScroll() {
|
||||
return mGestureEndTarget != HOME;
|
||||
}
|
||||
|
||||
private void onLauncherStart(final T activity) {
|
||||
if (TestProtocol.sDebugTracing) {
|
||||
Log.d(TestProtocol.NO_OVERVIEW_EVENT_TAG, "onLauncherStart");
|
||||
@@ -654,20 +610,18 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> extends
|
||||
updateLauncherTransitionProgress();
|
||||
}
|
||||
|
||||
@UiThread
|
||||
@Override
|
||||
public Intent getLaunchIntent() {
|
||||
return mOverviewComponentObserver.getOverviewIntent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateFinalShift() {
|
||||
float shift = mCurrentShift.value;
|
||||
|
||||
SwipeAnimationTargetSet controller = mRecentsAnimationWrapper.getController();
|
||||
if (controller != null) {
|
||||
float offsetX = mRecentsView == null ? 0 : mRecentsView.getScrollOffset();
|
||||
float offsetScale = getTaskCurveScaleForOffsetX(offsetX,
|
||||
mClipAnimationHelper.getTargetRect().width());
|
||||
mTransformParams.setProgress(shift).setOffsetX(offsetX).setOffsetScale(offsetScale);
|
||||
mClipAnimationHelper.applyTransform(mRecentsAnimationWrapper.targetSet,
|
||||
mTransformParams);
|
||||
updateSysUiFlags(shift);
|
||||
applyTransformUnchecked();
|
||||
updateSysUiFlags(mCurrentShift.value);
|
||||
}
|
||||
|
||||
if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
|
||||
@@ -817,8 +771,8 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> extends
|
||||
handleNormalGestureEnd(endVelocity, isFling, velocity, false /* isCancel */);
|
||||
}
|
||||
|
||||
@UiThread
|
||||
private InputConsumer createNewInputProxyHandler() {
|
||||
@Override
|
||||
protected InputConsumer createNewInputProxyHandler() {
|
||||
endRunningWindowAnim(true /* cancel */);
|
||||
endLauncherTransitionController();
|
||||
if (!ENABLE_QUICKSTEP_LIVE_TILE.get()) {
|
||||
@@ -1208,40 +1162,15 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> extends
|
||||
|
||||
@UiThread
|
||||
private void startNewTask() {
|
||||
// Launch the task user scrolled to (mRecentsView.getNextPage()).
|
||||
if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
|
||||
// We finish recents animation inside launchTask() when live tile is enabled.
|
||||
mRecentsView.getTaskViewAt(mRecentsView.getNextPage()).launchTask(false /* animate */,
|
||||
true /* freezeTaskList */);
|
||||
} else {
|
||||
int taskId = mRecentsView.getTaskViewAt(mRecentsView.getNextPage()).getTask().key.id;
|
||||
mFinishingRecentsAnimationForNewTaskId = taskId;
|
||||
mRecentsAnimationWrapper.finish(true /* toRecents */, () -> {
|
||||
if (!mCanceled) {
|
||||
TaskView nextTask = mRecentsView.getTaskView(taskId);
|
||||
if (nextTask != null) {
|
||||
nextTask.launchTask(false /* animate */, true /* freezeTaskList */,
|
||||
success -> {
|
||||
if (!success) {
|
||||
// We couldn't launch the task, so take user to overview so they can
|
||||
// decide what to do instead of staying in this broken state.
|
||||
endLauncherTransitionController();
|
||||
mActivityControlHelper.onLaunchTaskFailed(mActivity);
|
||||
nextTask.notifyTaskLaunchFailed(TAG);
|
||||
updateSysUiFlags(1 /* windowProgress == overview */);
|
||||
} else {
|
||||
mActivityControlHelper.onLaunchTaskSuccess(mActivity);
|
||||
}
|
||||
}, mMainThreadHandler);
|
||||
doLogGesture(NEW_TASK);
|
||||
}
|
||||
reset();
|
||||
}
|
||||
mCanceled = false;
|
||||
mFinishingRecentsAnimationForNewTaskId = -1;
|
||||
});
|
||||
}
|
||||
TOUCH_INTERACTION_LOG.addLog("finishRecentsAnimation", true);
|
||||
startNewTask(STATE_HANDLER_INVALIDATED, success -> {
|
||||
if (!success) {
|
||||
// We couldn't launch the task, so take user to overview so they can
|
||||
// decide what to do instead of staying in this broken state.
|
||||
endLauncherTransitionController();
|
||||
updateSysUiFlags(1 /* windowProgress == overview */);
|
||||
}
|
||||
doLogGesture(NEW_TASK);
|
||||
});
|
||||
}
|
||||
|
||||
private void reset() {
|
||||
|
||||
+12
@@ -87,6 +87,12 @@ public class FallbackRecentsView extends RecentsView<RecentsActivity> {
|
||||
super.draw(canvas);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
super.reset();
|
||||
resetViewUI();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void getTaskSize(DeviceProfile dp, Rect outRect) {
|
||||
LayoutUtils.calculateFallbackTaskSize(getContext(), dp, outRect);
|
||||
@@ -114,6 +120,12 @@ public class FallbackRecentsView extends RecentsView<RecentsActivity> {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetTaskVisuals() {
|
||||
super.resetTaskVisuals();
|
||||
setFullscreenProgress(mFullscreenProgress);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
|
||||
super.onLayout(changed, left, top, right, bottom);
|
||||
|
||||
+244
-60
@@ -15,15 +15,16 @@
|
||||
*/
|
||||
package com.android.quickstep.inputconsumers;
|
||||
|
||||
import static com.android.quickstep.MultiStateCallback.DEBUG_STATES;
|
||||
import static com.android.quickstep.RecentsActivity.EXTRA_TASK_ID;
|
||||
import static com.android.quickstep.RecentsActivity.EXTRA_THUMBNAIL;
|
||||
import static com.android.quickstep.inputconsumers.FallbackNoButtonInputConsumer.GestureEndTarget.NEW_TASK;
|
||||
import static com.android.quickstep.WindowTransformSwipeHandler.MIN_PROGRESS_FOR_OVERVIEW;
|
||||
import static com.android.quickstep.inputconsumers.FallbackNoButtonInputConsumer.GestureEndTarget.HOME;
|
||||
import static com.android.quickstep.inputconsumers.FallbackNoButtonInputConsumer.GestureEndTarget.LAST_TASK;
|
||||
import static com.android.quickstep.inputconsumers.FallbackNoButtonInputConsumer.GestureEndTarget.RECENTS;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorListenerAdapter;
|
||||
import android.animation.AnimatorSet;
|
||||
import android.app.ActivityManager.RunningTaskInfo;
|
||||
import android.app.ActivityOptions;
|
||||
@@ -34,24 +35,53 @@ import android.graphics.Rect;
|
||||
import android.os.Bundle;
|
||||
import android.view.WindowManager;
|
||||
|
||||
import com.android.launcher3.DeviceProfile;
|
||||
import com.android.launcher3.InvariantDeviceProfile;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.quickstep.ActivityControlHelper;
|
||||
import com.android.launcher3.anim.AnimationSuccessListener;
|
||||
import com.android.quickstep.AnimatedFloat;
|
||||
import com.android.quickstep.BaseSwipeUpHandler;
|
||||
import com.android.quickstep.MultiStateCallback;
|
||||
import com.android.quickstep.OverviewComponentObserver;
|
||||
import com.android.quickstep.RecentsActivity;
|
||||
import com.android.quickstep.RecentsModel;
|
||||
import com.android.quickstep.SwipeSharedState;
|
||||
import com.android.quickstep.fallback.FallbackRecentsView;
|
||||
import com.android.quickstep.util.ObjectWrapper;
|
||||
import com.android.quickstep.util.SwipeAnimationTargetSet;
|
||||
import com.android.quickstep.views.TaskView;
|
||||
import com.android.systemui.shared.recents.model.ThumbnailData;
|
||||
import com.android.systemui.shared.system.ActivityOptionsCompat;
|
||||
import com.android.systemui.shared.system.InputConsumerController;
|
||||
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
|
||||
|
||||
public class FallbackNoButtonInputConsumer extends BaseSwipeUpHandler {
|
||||
public class FallbackNoButtonInputConsumer extends BaseSwipeUpHandler<RecentsActivity> {
|
||||
|
||||
private static final String[] STATE_NAMES = DEBUG_STATES ? new String[5] : null;
|
||||
|
||||
private static int getFlagForIndex(int index, String name) {
|
||||
if (DEBUG_STATES) {
|
||||
STATE_NAMES[index] = name;
|
||||
}
|
||||
return 1 << index;
|
||||
}
|
||||
|
||||
private static final int STATE_RECENTS_PRESENT =
|
||||
getFlagForIndex(0, "STATE_RECENTS_PRESENT");
|
||||
private static final int STATE_HANDLER_INVALIDATED =
|
||||
getFlagForIndex(1, "STATE_HANDLER_INVALIDATED");
|
||||
|
||||
private static final int STATE_GESTURE_CANCELLED =
|
||||
getFlagForIndex(2, "STATE_GESTURE_CANCELLED");
|
||||
private static final int STATE_GESTURE_COMPLETED =
|
||||
getFlagForIndex(3, "STATE_GESTURE_COMPLETED");
|
||||
private static final int STATE_APP_CONTROLLER_RECEIVED =
|
||||
getFlagForIndex(4, "STATE_APP_CONTROLLER_RECEIVED");
|
||||
|
||||
public enum GestureEndTarget {
|
||||
HOME(3, 100, 1),
|
||||
RECENTS(1, 300, 0),
|
||||
LAST_TASK(0, 150, 1);
|
||||
LAST_TASK(0, 150, 1),
|
||||
NEW_TASK(0, 150, 1);
|
||||
|
||||
private final float mEndProgress;
|
||||
private final long mDurationMultiplier;
|
||||
@@ -64,53 +94,131 @@ public class FallbackNoButtonInputConsumer extends BaseSwipeUpHandler {
|
||||
}
|
||||
}
|
||||
|
||||
private final ActivityControlHelper mActivityControlHelper;
|
||||
private final OverviewComponentObserver mOverviewComponentObserver;
|
||||
private final int mRunningTaskId;
|
||||
|
||||
private final DeviceProfile mDP;
|
||||
private final Rect mTargetRect = new Rect();
|
||||
|
||||
private final AnimatedFloat mLauncherAlpha = new AnimatedFloat(this::onLauncherAlphaChanged);
|
||||
|
||||
private SwipeAnimationTargetSet mSwipeAnimationTargetSet;
|
||||
|
||||
private boolean mIsMotionPaused = false;
|
||||
private GestureEndTarget mEndTarget;
|
||||
|
||||
private final boolean mInQuickSwitchMode;
|
||||
private final boolean mContinuingLastGesture;
|
||||
|
||||
private Animator mFinishAnimation;
|
||||
|
||||
public FallbackNoButtonInputConsumer(Context context,
|
||||
OverviewComponentObserver overviewComponentObserver,
|
||||
RunningTaskInfo runningTaskInfo) {
|
||||
super(context);
|
||||
mOverviewComponentObserver = overviewComponentObserver;
|
||||
mActivityControlHelper = overviewComponentObserver.getActivityControlHelper();
|
||||
RunningTaskInfo runningTaskInfo, RecentsModel recentsModel,
|
||||
InputConsumerController inputConsumer,
|
||||
boolean isLikelyToStartNewTask, boolean continuingLastGesture) {
|
||||
super(context, overviewComponentObserver, recentsModel, inputConsumer);
|
||||
mRunningTaskId = runningTaskInfo.id;
|
||||
mDP = InvariantDeviceProfile.INSTANCE.get(context).getDeviceProfile(context).copy(context);
|
||||
mDp = InvariantDeviceProfile.INSTANCE.get(context).getDeviceProfile(context).copy(context);
|
||||
mLauncherAlpha.value = 1;
|
||||
|
||||
mInQuickSwitchMode = isLikelyToStartNewTask || continuingLastGesture;
|
||||
mContinuingLastGesture = continuingLastGesture;
|
||||
mClipAnimationHelper.setBaseAlphaCallback((t, a) -> mLauncherAlpha.value);
|
||||
initStateCallbacks();
|
||||
initTransitionTarget();
|
||||
}
|
||||
|
||||
private void initStateCallbacks() {
|
||||
mStateCallback = new MultiStateCallback(STATE_NAMES);
|
||||
|
||||
mStateCallback.addCallback(STATE_HANDLER_INVALIDATED,
|
||||
this::onHandlerInvalidated);
|
||||
mStateCallback.addCallback(STATE_RECENTS_PRESENT | STATE_HANDLER_INVALIDATED,
|
||||
this::onHandlerInvalidatedWithRecents);
|
||||
|
||||
mStateCallback.addCallback(STATE_GESTURE_CANCELLED | STATE_APP_CONTROLLER_RECEIVED,
|
||||
this::finishAnimationTargetSetAnimationComplete);
|
||||
|
||||
if (mInQuickSwitchMode) {
|
||||
mStateCallback.addCallback(STATE_GESTURE_COMPLETED | STATE_APP_CONTROLLER_RECEIVED
|
||||
| STATE_RECENTS_PRESENT,
|
||||
this::finishAnimationTargetSet);
|
||||
} else {
|
||||
mStateCallback.addCallback(STATE_GESTURE_COMPLETED | STATE_APP_CONTROLLER_RECEIVED,
|
||||
this::finishAnimationTargetSet);
|
||||
}
|
||||
}
|
||||
|
||||
private void onLauncherAlphaChanged() {
|
||||
if (mSwipeAnimationTargetSet != null && mEndTarget == null) {
|
||||
mClipAnimationHelper.applyTransform(mSwipeAnimationTargetSet, mTransformParams);
|
||||
if (mRecentsAnimationWrapper.targetSet != null && mEndTarget == null) {
|
||||
applyTransformUnchecked();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean onActivityInit(final RecentsActivity activity, Boolean alreadyOnHome) {
|
||||
mActivity = activity;
|
||||
mRecentsView = activity.getOverviewPanel();
|
||||
linkRecentsViewScroll();
|
||||
mRecentsView.setDisallowScrollToClearAll(true);
|
||||
mRecentsView.getClearAllButton().setVisibilityAlpha(0);
|
||||
|
||||
((FallbackRecentsView) mRecentsView).setZoomProgress(1);
|
||||
|
||||
if (!mContinuingLastGesture) {
|
||||
mRecentsView.onGestureAnimationStart(mRunningTaskId);
|
||||
}
|
||||
setStateOnUiThread(STATE_RECENTS_PRESENT);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean moveWindowWithRecentsScroll() {
|
||||
return mInQuickSwitchMode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initWhenReady() {
|
||||
if (mInQuickSwitchMode) {
|
||||
// Only init if we are in quickswitch mode
|
||||
super.initWhenReady();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateDisplacement(float displacement) {
|
||||
if (!mInQuickSwitchMode) {
|
||||
super.updateDisplacement(displacement);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected InputConsumer createNewInputProxyHandler() {
|
||||
// Just consume all input on the active task
|
||||
return InputConsumer.NO_OP;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMotionPauseChanged(boolean isPaused) {
|
||||
mIsMotionPaused = isPaused;
|
||||
mLauncherAlpha.animateToValue(mLauncherAlpha.value, isPaused ? 0 : 1)
|
||||
.setDuration(150).start();
|
||||
performHapticFeedback();
|
||||
if (!mInQuickSwitchMode) {
|
||||
mIsMotionPaused = isPaused;
|
||||
mLauncherAlpha.animateToValue(mLauncherAlpha.value, isPaused ? 0 : 1)
|
||||
.setDuration(150).start();
|
||||
performHapticFeedback();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Intent getLaunchIntent() {
|
||||
if (mInQuickSwitchMode) {
|
||||
return mOverviewComponentObserver.getOverviewIntent();
|
||||
} else {
|
||||
return mOverviewComponentObserver.getHomeIntent();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateFinalShift() {
|
||||
mTransformParams.setProgress(mCurrentShift.value);
|
||||
if (mSwipeAnimationTargetSet != null) {
|
||||
mClipAnimationHelper.applyTransform(mSwipeAnimationTargetSet, mTransformParams);
|
||||
if (mRecentsAnimationWrapper.targetSet != null) {
|
||||
applyTransformUnchecked();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -118,41 +226,90 @@ public class FallbackNoButtonInputConsumer extends BaseSwipeUpHandler {
|
||||
public void onGestureCancelled() {
|
||||
updateDisplacement(0);
|
||||
mEndTarget = LAST_TASK;
|
||||
finishAnimationTargetSetAnimationComplete();
|
||||
setStateOnUiThread(STATE_GESTURE_CANCELLED);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onGestureEnded(float endVelocity, PointF velocity, PointF downPos) {
|
||||
float flingThreshold = mContext.getResources()
|
||||
.getDimension(R.dimen.quickstep_fling_threshold_velocity);
|
||||
boolean isFling = Math.abs(endVelocity) > flingThreshold;
|
||||
|
||||
if (isFling) {
|
||||
mEndTarget = endVelocity < 0 ? HOME : LAST_TASK;
|
||||
} else if (mIsMotionPaused) {
|
||||
mEndTarget = RECENTS;
|
||||
if (mInQuickSwitchMode) {
|
||||
// For now set it to non-null, it will be reset before starting the animation
|
||||
mEndTarget = LAST_TASK;
|
||||
} else {
|
||||
mEndTarget = mCurrentShift.value >= MIN_PROGRESS_FOR_OVERVIEW ? HOME : LAST_TASK;
|
||||
float flingThreshold = mContext.getResources()
|
||||
.getDimension(R.dimen.quickstep_fling_threshold_velocity);
|
||||
boolean isFling = Math.abs(endVelocity) > flingThreshold;
|
||||
|
||||
if (isFling) {
|
||||
mEndTarget = endVelocity < 0 ? HOME : LAST_TASK;
|
||||
} else if (mIsMotionPaused) {
|
||||
mEndTarget = RECENTS;
|
||||
} else {
|
||||
mEndTarget = mCurrentShift.value >= MIN_PROGRESS_FOR_OVERVIEW ? HOME : LAST_TASK;
|
||||
}
|
||||
}
|
||||
if (mSwipeAnimationTargetSet != null) {
|
||||
finishAnimationTargetSet();
|
||||
setStateOnUiThread(STATE_GESTURE_COMPLETED);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConsumerAboutToBeSwitched(SwipeSharedState sharedState) {
|
||||
if (mInQuickSwitchMode && mEndTarget != null) {
|
||||
sharedState.canGestureBeContinued = true;
|
||||
sharedState.goingToLauncher = false;
|
||||
|
||||
mCanceled = true;
|
||||
mCurrentShift.cancelAnimation();
|
||||
if (mFinishAnimation != null) {
|
||||
mFinishAnimation.cancel();
|
||||
}
|
||||
|
||||
if (mRecentsView != null) {
|
||||
if (mFinishingRecentsAnimationForNewTaskId != -1) {
|
||||
TaskView newRunningTaskView = mRecentsView.getTaskView(
|
||||
mFinishingRecentsAnimationForNewTaskId);
|
||||
int newRunningTaskId = newRunningTaskView != null
|
||||
? newRunningTaskView.getTask().key.id
|
||||
: -1;
|
||||
mRecentsView.setCurrentTask(newRunningTaskId);
|
||||
sharedState.setRecentsAnimationFinishInterrupted(newRunningTaskId);
|
||||
}
|
||||
mRecentsView.setOnScrollChangeListener(null);
|
||||
}
|
||||
} else {
|
||||
setStateOnUiThread(STATE_HANDLER_INVALIDATED);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void onHandlerInvalidated() {
|
||||
mActivityInitListener.unregister();
|
||||
if (mGestureEndCallback != null) {
|
||||
mGestureEndCallback.run();
|
||||
}
|
||||
}
|
||||
|
||||
private void onHandlerInvalidatedWithRecents() {
|
||||
mRecentsView.onGestureAnimationEnd();
|
||||
mRecentsView.setDisallowScrollToClearAll(false);
|
||||
mRecentsView.getClearAllButton().setVisibilityAlpha(1);
|
||||
}
|
||||
|
||||
|
||||
private void finishAnimationTargetSetAnimationComplete() {
|
||||
switch (mEndTarget) {
|
||||
case HOME:
|
||||
mSwipeAnimationTargetSet.finishController(true, null, true);
|
||||
mRecentsAnimationWrapper.finish(true, null, true);
|
||||
break;
|
||||
case LAST_TASK:
|
||||
mSwipeAnimationTargetSet.finishController(false, null, false);
|
||||
mRecentsAnimationWrapper.finish(false, null, false);
|
||||
break;
|
||||
case RECENTS: {
|
||||
ThumbnailData thumbnail =
|
||||
mSwipeAnimationTargetSet.controller.screenshotTask(mRunningTaskId);
|
||||
mSwipeAnimationTargetSet.controller.setCancelWithDeferredScreenshot(true);
|
||||
mRecentsAnimationWrapper.targetSet.controller.screenshotTask(mRunningTaskId);
|
||||
mRecentsAnimationWrapper.setCancelWithDeferredScreenshot(true);
|
||||
|
||||
ActivityOptions options = ActivityOptions.makeCustomAnimation(mContext, 0, 0);
|
||||
ActivityOptionsCompat.setFreezeRecentTasksList(options);
|
||||
|
||||
Bundle extras = new Bundle();
|
||||
extras.putBinder(EXTRA_THUMBNAIL, new ObjectWrapper<>(thumbnail));
|
||||
extras.putInt(EXTRA_TASK_ID, mRunningTaskId);
|
||||
@@ -160,33 +317,58 @@ public class FallbackNoButtonInputConsumer extends BaseSwipeUpHandler {
|
||||
Intent intent = new Intent(mOverviewComponentObserver.getOverviewIntent())
|
||||
.putExtras(extras);
|
||||
mContext.startActivity(intent, options.toBundle());
|
||||
mSwipeAnimationTargetSet.controller.cleanupScreenshot();
|
||||
mRecentsAnimationWrapper.targetSet.controller.cleanupScreenshot();
|
||||
break;
|
||||
}
|
||||
case NEW_TASK: {
|
||||
startNewTask(STATE_HANDLER_INVALIDATED, b -> {});
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (mGestureEndCallback != null) {
|
||||
mGestureEndCallback.run();
|
||||
}
|
||||
|
||||
setStateOnUiThread(STATE_HANDLER_INVALIDATED);
|
||||
}
|
||||
|
||||
private void finishAnimationTargetSet() {
|
||||
if (mInQuickSwitchMode) {
|
||||
// Recalculate the end target, some views might have been initialized after
|
||||
// gesture has ended.
|
||||
if (mRecentsView == null || !mRecentsAnimationWrapper.hasTargets()) {
|
||||
mEndTarget = LAST_TASK;
|
||||
} else {
|
||||
final int runningTaskIndex = mRecentsView.getRunningTaskIndex();
|
||||
final int taskToLaunch = mRecentsView.getNextPage();
|
||||
mEndTarget = (runningTaskIndex >= 0 && taskToLaunch != runningTaskIndex)
|
||||
? NEW_TASK : LAST_TASK;
|
||||
}
|
||||
}
|
||||
|
||||
float endProgress = mEndTarget.mEndProgress;
|
||||
|
||||
if (mCurrentShift.value != endProgress) {
|
||||
if (mCurrentShift.value != endProgress || mInQuickSwitchMode) {
|
||||
AnimatorSet anim = new AnimatorSet();
|
||||
anim.play(mLauncherAlpha.animateToValue(
|
||||
mLauncherAlpha.value, mEndTarget.mLauncherAlpha));
|
||||
anim.play(mCurrentShift.animateToValue(mCurrentShift.value, endProgress));
|
||||
|
||||
anim.setDuration((long) (mEndTarget.mDurationMultiplier *
|
||||
Math.abs(endProgress - mCurrentShift.value)));
|
||||
anim.addListener(new AnimatorListenerAdapter() {
|
||||
|
||||
long duration = (long) (mEndTarget.mDurationMultiplier *
|
||||
Math.abs(endProgress - mCurrentShift.value));
|
||||
if (mRecentsView != null) {
|
||||
duration = Math.max(duration, mRecentsView.getScroller().getDuration());
|
||||
}
|
||||
|
||||
anim.setDuration(duration);
|
||||
anim.addListener(new AnimationSuccessListener() {
|
||||
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
public void onAnimationSuccess(Animator animator) {
|
||||
finishAnimationTargetSetAnimationComplete();
|
||||
mFinishAnimation = null;
|
||||
}
|
||||
});
|
||||
anim.start();
|
||||
mFinishAnimation = anim;
|
||||
} else {
|
||||
finishAnimationTargetSetAnimationComplete();
|
||||
}
|
||||
@@ -194,34 +376,36 @@ public class FallbackNoButtonInputConsumer extends BaseSwipeUpHandler {
|
||||
|
||||
@Override
|
||||
public void onRecentsAnimationStart(SwipeAnimationTargetSet targetSet) {
|
||||
mSwipeAnimationTargetSet = targetSet;
|
||||
Rect overviewStackBounds = new Rect(0, 0, mDP.widthPx, mDP.heightPx);
|
||||
mRecentsAnimationWrapper.setController(targetSet);
|
||||
mRecentsAnimationWrapper.enableInputConsumer();
|
||||
Rect overviewStackBounds = new Rect(0, 0, mDp.widthPx, mDp.heightPx);
|
||||
RemoteAnimationTargetCompat runningTaskTarget = targetSet.findTask(mRunningTaskId);
|
||||
|
||||
mDP.updateIsSeascape(mContext.getSystemService(WindowManager.class));
|
||||
mDp.updateIsSeascape(mContext.getSystemService(WindowManager.class));
|
||||
if (targetSet.homeContentInsets != null) {
|
||||
mDP.updateInsets(targetSet.homeContentInsets);
|
||||
mDp.updateInsets(targetSet.homeContentInsets);
|
||||
}
|
||||
|
||||
if (runningTaskTarget != null) {
|
||||
mClipAnimationHelper.updateSource(overviewStackBounds, runningTaskTarget);
|
||||
}
|
||||
mClipAnimationHelper.prepareAnimation(mDP, false /* isOpening */);
|
||||
mClipAnimationHelper.prepareAnimation(mDp, false /* isOpening */);
|
||||
initTransitionTarget();
|
||||
mClipAnimationHelper.applyTransform(mSwipeAnimationTargetSet, mTransformParams);
|
||||
applyTransformUnchecked();
|
||||
|
||||
if (mEndTarget != null) {
|
||||
finishAnimationTargetSet();
|
||||
}
|
||||
setStateOnUiThread(STATE_APP_CONTROLLER_RECEIVED);
|
||||
}
|
||||
|
||||
private void initTransitionTarget() {
|
||||
mTransitionDragLength = mActivityControlHelper.getSwipeUpDestinationAndLength(
|
||||
mDP, mContext, mTargetRect);
|
||||
mDragLengthFactor = (float) mDP.heightPx / mTransitionDragLength;
|
||||
mDp, mContext, mTargetRect);
|
||||
mDragLengthFactor = (float) mDp.heightPx / mTransitionDragLength;
|
||||
mClipAnimationHelper.updateTargetRect(mTargetRect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRecentsAnimationCanceled() { }
|
||||
public void onRecentsAnimationCanceled() {
|
||||
mRecentsAnimationWrapper.setController(null);
|
||||
setStateOnUiThread(STATE_HANDLER_INVALIDATED);
|
||||
}
|
||||
}
|
||||
|
||||
+14
-13
@@ -35,7 +35,6 @@ import android.annotation.TargetApi;
|
||||
import android.app.ActivityManager.RunningTaskInfo;
|
||||
import android.content.Context;
|
||||
import android.content.ContextWrapper;
|
||||
import android.content.Intent;
|
||||
import android.graphics.PointF;
|
||||
import android.graphics.RectF;
|
||||
import android.os.Build;
|
||||
@@ -79,7 +78,6 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC
|
||||
|
||||
private final CachedEventDispatcher mRecentsViewDispatcher = new CachedEventDispatcher();
|
||||
private final RunningTaskInfo mRunningTask;
|
||||
private final Intent mHomeIntent;
|
||||
private final OverviewCallbacks mOverviewCallbacks;
|
||||
private final SwipeSharedState mSwipeSharedState;
|
||||
private final InputMonitorCompat mInputMonitorCompat;
|
||||
@@ -117,12 +115,13 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC
|
||||
private float mStartDisplacement;
|
||||
|
||||
private Handler mMainThreadHandler;
|
||||
private Runnable mCancelRecentsAnimationRunnable = () ->
|
||||
private Runnable mCancelRecentsAnimationRunnable = () -> {
|
||||
ActivityManagerWrapper.getInstance().cancelRecentsAnimation(
|
||||
true /* restoreHomeStackPosition */);
|
||||
};
|
||||
|
||||
public OtherActivityInputConsumer(Context base, RunningTaskInfo runningTaskInfo,
|
||||
Intent homeIntent, boolean isDeferredDownTarget, OverviewCallbacks overviewCallbacks,
|
||||
boolean isDeferredDownTarget, OverviewCallbacks overviewCallbacks,
|
||||
Consumer<OtherActivityInputConsumer> onCompleteCallback,
|
||||
SwipeSharedState swipeSharedState, InputMonitorCompat inputMonitorCompat,
|
||||
RectF swipeTouchRegion, boolean disableHorizontalSwipe,
|
||||
@@ -131,7 +130,6 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC
|
||||
|
||||
mMainThreadHandler = new Handler(Looper.getMainLooper());
|
||||
mRunningTask = runningTaskInfo;
|
||||
mHomeIntent = homeIntent;
|
||||
mMode = SysUINavigationMode.getMode(base);
|
||||
mSwipeTouchRegion = swipeTouchRegion;
|
||||
mHandlerFactory = handlerFactory;
|
||||
@@ -204,7 +202,7 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC
|
||||
// Start the window animation on down to give more time for launcher to draw if the
|
||||
// user didn't start the gesture over the back button
|
||||
if (!mIsDeferredDownTarget) {
|
||||
startTouchTrackingForWindowAnimation(ev.getEventTime());
|
||||
startTouchTrackingForWindowAnimation(ev.getEventTime(), false);
|
||||
}
|
||||
|
||||
RaceConditionTracker.onEvent(DOWN_EVT, EXIT);
|
||||
@@ -253,6 +251,10 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC
|
||||
}
|
||||
}
|
||||
|
||||
float horizontalDist = Math.abs(displacementX);
|
||||
float upDist = -displacement;
|
||||
boolean isLikelyToStartNewTask = horizontalDist > upDist;
|
||||
|
||||
if (!mPassedPilferInputSlop) {
|
||||
float displacementY = mLastPos.y - mDownPos.y;
|
||||
if (squaredHypot(displacementX, displacementY) >= mSquaredTouchSlop) {
|
||||
@@ -268,7 +270,8 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC
|
||||
if (mIsDeferredDownTarget) {
|
||||
// Deferred gesture, start the animation and gesture tracking once
|
||||
// we pass the actual touch slop
|
||||
startTouchTrackingForWindowAnimation(ev.getEventTime());
|
||||
startTouchTrackingForWindowAnimation(
|
||||
ev.getEventTime(), isLikelyToStartNewTask);
|
||||
}
|
||||
if (!mPassedWindowMoveSlop) {
|
||||
mPassedWindowMoveSlop = true;
|
||||
@@ -286,9 +289,6 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC
|
||||
}
|
||||
|
||||
if (mMode == Mode.NO_BUTTON) {
|
||||
float horizontalDist = Math.abs(displacementX);
|
||||
float upDist = -displacement;
|
||||
boolean isLikelyToStartNewTask = horizontalDist > upDist;
|
||||
mMotionPauseDetector.setDisallowPause(upDist < mMotionPauseMinDisplacement
|
||||
|| isLikelyToStartNewTask);
|
||||
mMotionPauseDetector.addPosition(displacement, ev.getEventTime());
|
||||
@@ -320,12 +320,13 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC
|
||||
mInteractionHandler.onGestureStarted();
|
||||
}
|
||||
|
||||
private void startTouchTrackingForWindowAnimation(long touchTimeMs) {
|
||||
private void startTouchTrackingForWindowAnimation(
|
||||
long touchTimeMs, boolean isLikelyToStartNewTask) {
|
||||
TOUCH_INTERACTION_LOG.addLog("startRecentsAnimation");
|
||||
|
||||
RecentsAnimationListenerSet listenerSet = mSwipeSharedState.getActiveListener();
|
||||
final BaseSwipeUpHandler handler = mHandlerFactory.newHandler(mRunningTask, touchTimeMs,
|
||||
listenerSet != null);
|
||||
listenerSet != null, isLikelyToStartNewTask);
|
||||
|
||||
mInteractionHandler = handler;
|
||||
handler.setGestureEndCallback(this::onInteractionGestureFinished);
|
||||
@@ -340,7 +341,7 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC
|
||||
RecentsAnimationListenerSet newListenerSet =
|
||||
mSwipeSharedState.newRecentsAnimationListenerSet();
|
||||
newListenerSet.addListener(handler);
|
||||
startRecentsActivityAsync(mHomeIntent, newListenerSet);
|
||||
startRecentsActivityAsync(handler.getLaunchIntent(), newListenerSet);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -289,7 +289,7 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
|
||||
@ViewDebug.ExportedProperty(category = "launcher")
|
||||
private float mContentAlpha = 1;
|
||||
@ViewDebug.ExportedProperty(category = "launcher")
|
||||
private float mFullscreenProgress = 0;
|
||||
protected float mFullscreenProgress = 0;
|
||||
|
||||
// Keeps track of task id whose visual state should not be reset
|
||||
private int mIgnoreResetTaskId = -1;
|
||||
@@ -604,6 +604,7 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
|
||||
TaskView taskView = (TaskView) getChildAt(i);
|
||||
if (mIgnoreResetTaskId != taskView.getTask().key.id) {
|
||||
taskView.resetVisualProperties();
|
||||
taskView.setStableAlpha(mContentAlpha);
|
||||
}
|
||||
}
|
||||
if (mRunningTaskTileHidden) {
|
||||
|
||||
Reference in New Issue
Block a user