diff --git a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java index 14b01fe7d1..e3427b7087 100644 --- a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java +++ b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java @@ -127,6 +127,7 @@ import com.android.quickstep.util.SurfaceTransaction; import com.android.quickstep.util.SurfaceTransactionApplier; import com.android.quickstep.util.SwipePipToHomeAnimator; import com.android.quickstep.util.TaskViewSimulator; +import com.android.quickstep.views.DesktopTaskView; import com.android.quickstep.views.RecentsView; import com.android.quickstep.views.TaskView; import com.android.systemui.shared.recents.model.Task; @@ -878,7 +879,11 @@ public abstract class AbsSwipeUpHandler, public void onRecentsAnimationStart(RecentsAnimationController controller, RecentsAnimationTargets targets) { super.onRecentsAnimationStart(controller, targets); - mRemoteTargetHandles = mTargetGluer.assignTargetsForSplitScreen(mContext, targets); + if (DesktopTaskView.DESKTOP_MODE_SUPPORTED && targets.hasDesktopTasks()) { + mRemoteTargetHandles = mTargetGluer.assignTargetsForDesktop(targets); + } else { + mRemoteTargetHandles = mTargetGluer.assignTargetsForSplitScreen(mContext, targets); + } mRecentsAnimationController = controller; mRecentsAnimationTargets = targets; mSwipePipToHomeReleaseCheck = new RemoteAnimationTargets.ReleaseCheck(); diff --git a/quickstep/src/com/android/quickstep/RecentsAnimationTargets.java b/quickstep/src/com/android/quickstep/RecentsAnimationTargets.java index 388e1256d8..15e1365998 100644 --- a/quickstep/src/com/android/quickstep/RecentsAnimationTargets.java +++ b/quickstep/src/com/android/quickstep/RecentsAnimationTargets.java @@ -15,11 +15,15 @@ */ package com.android.quickstep; +import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM; import static android.view.RemoteAnimationTarget.MODE_CLOSING; +import android.app.WindowConfiguration; import android.graphics.Rect; import android.view.RemoteAnimationTarget; +import com.android.quickstep.views.DesktopTaskView; + /** * Extension of {@link RemoteAnimationTargets} with additional information about swipe * up animation @@ -40,4 +44,22 @@ public class RecentsAnimationTargets extends RemoteAnimationTargets { public boolean hasTargets() { return unfilteredApps.length != 0; } + + /** + * Check if target apps contain desktop tasks which have windowing mode set to {@link + * WindowConfiguration#WINDOWING_MODE_FREEFORM} + * + * @return {@code true} if at least one target app is a desktop task + */ + public boolean hasDesktopTasks() { + if (!DesktopTaskView.DESKTOP_MODE_SUPPORTED) { + return false; + } + for (RemoteAnimationTarget target : apps) { + if (target.windowConfiguration.getWindowingMode() == WINDOWING_MODE_FREEFORM) { + return true; + } + } + return false; + } } diff --git a/quickstep/src/com/android/quickstep/RemoteTargetGluer.java b/quickstep/src/com/android/quickstep/RemoteTargetGluer.java index 4c41bef26a..9b00dcf765 100644 --- a/quickstep/src/com/android/quickstep/RemoteTargetGluer.java +++ b/quickstep/src/com/android/quickstep/RemoteTargetGluer.java @@ -26,6 +26,7 @@ import com.android.launcher3.util.SplitConfigurationOptions.SplitBounds; import com.android.quickstep.util.AnimatorControllerWithResistance; import com.android.quickstep.util.TaskViewSimulator; import com.android.quickstep.util.TransformParams; +import com.android.quickstep.views.DesktopTaskView; import java.util.ArrayList; @@ -41,8 +42,8 @@ public class RemoteTargetGluer { * Use this constructor if remote targets are split-screen independent */ public RemoteTargetGluer(Context context, BaseActivityInterface sizingStrategy, - RemoteAnimationTargets targets) { - mRemoteTargetHandles = createHandles(context, sizingStrategy, targets.apps.length); + RemoteAnimationTargets targets, boolean forDesktop) { + init(context, sizingStrategy, targets.apps.length, forDesktop); } /** @@ -50,15 +51,31 @@ public class RemoteTargetGluer { * running tasks */ public RemoteTargetGluer(Context context, BaseActivityInterface sizingStrategy) { + if (DesktopTaskView.DESKTOP_MODE_SUPPORTED) { + // TODO: binder call, only for prototyping. Creating the gluer should be postponed so + // we can create it when we have the remote animation targets ready. + int desktopTasks = SystemUiProxy.INSTANCE.get(context).getVisibleDesktopTaskCount(); + if (desktopTasks > 0) { + init(context, sizingStrategy, desktopTasks, true /* forDesktop */); + return; + } + } + int[] splitIds = TopTaskTracker.INSTANCE.get(context).getRunningSplitTaskIds(); - mRemoteTargetHandles = createHandles(context, sizingStrategy, splitIds.length == 2 ? 2 : 1); + init(context, sizingStrategy, splitIds.length == 2 ? 2 : 1, false /* forDesktop */); + } + + private void init(Context context, BaseActivityInterface sizingStrategy, int numHandles, + boolean forDesktop) { + mRemoteTargetHandles = createHandles(context, sizingStrategy, numHandles, forDesktop); } private RemoteTargetHandle[] createHandles(Context context, - BaseActivityInterface sizingStrategy, int numHandles) { + BaseActivityInterface sizingStrategy, int numHandles, boolean forDesktop) { RemoteTargetHandle[] handles = new RemoteTargetHandle[numHandles]; for (int i = 0; i < numHandles; i++) { TaskViewSimulator tvs = new TaskViewSimulator(context, sizingStrategy); + tvs.setIsDesktopTask(forDesktop); TransformParams transformParams = new TransformParams(); handles[i] = new RemoteTargetHandle(tvs, transformParams); } @@ -135,6 +152,20 @@ public class RemoteTargetGluer { return mRemoteTargetHandles; } + /** + * Similar to {@link #assignTargets(RemoteAnimationTargets)}, except this creates distinct + * transform params per app in {@code targets.apps} list. + */ + public RemoteTargetHandle[] assignTargetsForDesktop(RemoteAnimationTargets targets) { + for (int i = 0; i < mRemoteTargetHandles.length; i++) { + RemoteAnimationTarget primaryTaskTarget = targets.apps[i]; + mRemoteTargetHandles[i].mTransformParams.setTargetSet( + createRemoteAnimationTargetsForTaskId(targets, primaryTaskTarget.taskId)); + mRemoteTargetHandles[i].mTaskViewSimulator.setPreview(primaryTaskTarget, null); + } + return mRemoteTargetHandles; + } + private Rect getStartBounds(RemoteAnimationTarget target) { return target.startBounds == null ? target.screenSpaceBounds : target.startBounds; } @@ -172,6 +203,33 @@ public class RemoteTargetGluer { filteredApps, targets.wallpapers, targets.nonApps, targets.targetMode); } + /** + * Ensures that we only animate one specific app target. Includes ancillary targets such as + * home/recents + * + * @param targets remote animation targets to filter + * @param taskId id for a task that we want this remote animation to apply to + * @return {@link RemoteAnimationTargets} where app target only includes the app that has the + * {@code taskId} that was passed in + */ + private RemoteAnimationTargets createRemoteAnimationTargetsForTaskId( + RemoteAnimationTargets targets, int taskId) { + RemoteAnimationTarget[] targetApp = null; + for (RemoteAnimationTarget targetCompat : targets.unfilteredApps) { + if (targetCompat.taskId == taskId) { + targetApp = new RemoteAnimationTarget[]{targetCompat}; + break; + } + } + + if (targetApp == null) { + targetApp = new RemoteAnimationTarget[0]; + } + + return new RemoteAnimationTargets(targetApp, targets.wallpapers, targets.nonApps, + targets.targetMode); + } + public RemoteTargetHandle[] getRemoteTargetHandles() { return mRemoteTargetHandles; } diff --git a/quickstep/src/com/android/quickstep/SystemUiProxy.java b/quickstep/src/com/android/quickstep/SystemUiProxy.java index 00fb7ec299..2200b35865 100644 --- a/quickstep/src/com/android/quickstep/SystemUiProxy.java +++ b/quickstep/src/com/android/quickstep/SystemUiProxy.java @@ -949,4 +949,16 @@ public class SystemUiProxy implements ISystemUiProxy { } } } + + /** Call shell to get number of visible freeform tasks */ + public int getVisibleDesktopTaskCount() { + if (mDesktopMode != null) { + try { + return mDesktopMode.getVisibleTaskCount(); + } catch (RemoteException e) { + Log.w(TAG, "Failed call getVisibleDesktopTaskCount", e); + } + } + return 0; + } } diff --git a/quickstep/src/com/android/quickstep/TaskViewUtils.java b/quickstep/src/com/android/quickstep/TaskViewUtils.java index 67de4b1679..1a72e3f746 100644 --- a/quickstep/src/com/android/quickstep/TaskViewUtils.java +++ b/quickstep/src/com/android/quickstep/TaskViewUtils.java @@ -39,6 +39,7 @@ import static com.android.launcher3.anim.Interpolators.LINEAR; import static com.android.launcher3.anim.Interpolators.TOUCH_RESPONSE_INTERPOLATOR; import static com.android.launcher3.anim.Interpolators.clampToProgress; import static com.android.launcher3.util.MultiPropertyFactory.MULTI_PROPERTY_VALUE; +import static com.android.quickstep.views.DesktopTaskView.DESKTOP_MODE_SUPPORTED; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; @@ -78,6 +79,7 @@ import com.android.quickstep.util.SurfaceTransaction.SurfaceProperties; import com.android.quickstep.util.SurfaceTransactionApplier; import com.android.quickstep.util.TaskViewSimulator; import com.android.quickstep.util.TransformParams; +import com.android.quickstep.views.DesktopTaskView; import com.android.quickstep.views.GroupedTaskView; import com.android.quickstep.views.RecentsView; import com.android.quickstep.views.TaskThumbnailView; @@ -182,9 +184,12 @@ public final class TaskViewUtils { // Re-use existing handles remoteTargetHandles = recentsViewHandles; } else { + boolean forDesktop = DESKTOP_MODE_SUPPORTED && v instanceof DesktopTaskView; RemoteTargetGluer gluer = new RemoteTargetGluer(v.getContext(), - recentsView.getSizeStrategy(), targets); - if (v.containsMultipleTasks()) { + recentsView.getSizeStrategy(), targets, forDesktop); + if (forDesktop) { + remoteTargetHandles = gluer.assignTargetsForDesktop(targets); + } else if (v.containsMultipleTasks()) { remoteTargetHandles = gluer.assignTargetsForSplitScreen(targets, v.getTaskIds()); } else { remoteTargetHandles = gluer.assignTargets(targets); diff --git a/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java b/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java index 04af19f729..69f9ce3447 100644 --- a/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java +++ b/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java @@ -104,6 +104,7 @@ public class TaskViewSimulator implements TransformParams.BuilderProxy { private SplitBounds mSplitBounds; private Boolean mDrawsBelowRecents = null; private boolean mIsGridTask; + private boolean mIsDesktopTask; private int mTaskRectTranslationX; private int mTaskRectTranslationY; @@ -145,6 +146,13 @@ public class TaskViewSimulator implements TransformParams.BuilderProxy { if (mDp == null) { return 1; } + + if (mIsDesktopTask) { + mTaskRect.set(mThumbnailPosition); + mPivot.set(mTaskRect.centerX(), mTaskRect.centerY()); + return 1; + } + if (mIsGridTask) { mSizeStrategy.calculateGridTaskSize(mContext, mDp, mTaskRect, mOrientationState.getOrientationHandler()); @@ -227,6 +235,13 @@ public class TaskViewSimulator implements TransformParams.BuilderProxy { mIsGridTask = isGridTask; } + /** + * Sets whether this task is part of desktop tasks in overview. + */ + public void setIsDesktopTask(boolean desktop) { + mIsDesktopTask = desktop; + } + /** * Apply translations on TaskRect's starting location. */ diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java index b481be344c..cdc0574daa 100644 --- a/quickstep/src/com/android/quickstep/views/RecentsView.java +++ b/quickstep/src/com/android/quickstep/views/RecentsView.java @@ -4911,9 +4911,16 @@ public abstract class RecentsView