From 107f85d20cca05dd3e29bb09eec0db2c0bfc4645 Mon Sep 17 00:00:00 2001 From: Xiaoqian Dai Date: Mon, 3 Mar 2025 23:40:15 +0000 Subject: [PATCH] desktop-exploded-view: Implement the activate window behavior Clicking on one task window in the desktop exploded view, it should activate that task window. Flag: com.android.launcher3.enable_desktop_exploded_view Test: Manual Bug: 353948437, 410888109 Change-Id: I1836bf0babcec039ef76b13ecd40f87a8ab4d822 --- .../DesktopRecentsTransitionController.kt | 14 ++++++-- .../com/android/quickstep/SystemUiProxy.kt | 33 +++++++++++++++---- .../com/android/quickstep/TaskViewUtils.java | 9 ++++- .../quickstep/util/TaskViewSimulator.java | 33 ++++++++++++++----- .../quickstep/views/DesktopTaskView.kt | 26 +++++++++++++-- .../quickstep/views/LauncherRecentsView.java | 3 +- 6 files changed, 96 insertions(+), 22 deletions(-) diff --git a/quickstep/src/com/android/launcher3/desktop/DesktopRecentsTransitionController.kt b/quickstep/src/com/android/launcher3/desktop/DesktopRecentsTransitionController.kt index a01846dda9..6d9b087647 100644 --- a/quickstep/src/com/android/launcher3/desktop/DesktopRecentsTransitionController.kt +++ b/quickstep/src/com/android/launcher3/desktop/DesktopRecentsTransitionController.kt @@ -46,10 +46,14 @@ class DesktopRecentsTransitionController( private val depthController: DepthController?, ) { - /** Launch desktop tasks from recents view */ + /** + * Launch desktop tasks from recents view and activate the new freeform task with id + * [taskIdToReorderToFront] if it's provided and already on the given desk. + */ fun launchDesktopFromRecents( desktopTaskView: DesktopTaskView, animated: Boolean, + taskIdToReorderToFront: Int? = null, callback: Consumer? = null, ) { val animRunner = @@ -62,9 +66,13 @@ class DesktopRecentsTransitionController( ) val transition = RemoteTransition(animRunner, appThread, "RecentsToDesktop") if (areMultiDesksFlagsEnabled()) { - systemUiProxy.activateDesk(desktopTaskView.deskId, transition) + systemUiProxy.activateDesk(desktopTaskView.deskId, transition, taskIdToReorderToFront) } else { - systemUiProxy.showDesktopApps(desktopTaskView.displayId, transition) + systemUiProxy.showDesktopApps( + desktopTaskView.displayId, + transition, + taskIdToReorderToFront, + ) } } diff --git a/quickstep/src/com/android/quickstep/SystemUiProxy.kt b/quickstep/src/com/android/quickstep/SystemUiProxy.kt index a7b9d41828..62138f8638 100644 --- a/quickstep/src/com/android/quickstep/SystemUiProxy.kt +++ b/quickstep/src/com/android/quickstep/SystemUiProxy.kt @@ -18,6 +18,7 @@ package com.android.quickstep import android.app.ActivityManager import android.app.ActivityManager.RunningTaskInfo import android.app.ActivityOptions +import android.app.ActivityTaskManager.INVALID_TASK_ID import android.app.PendingIntent import android.content.ComponentName import android.content.Context @@ -1109,11 +1110,18 @@ class SystemUiProxy @Inject constructor(@ApplicationContext private val context: /** * Calls shell to activate the desk whose ID is `deskId` on whatever display it exists on. This - * will bring all tasks on this desk to the front. + * will show all tasks on this desk and bring [taskIdToReorderToFront] to the front if it's + * provided and already on the given desk. If the provided [taskIdToReorderToFront]'s value is + * null, do not change the windows' activation on the desk. */ - fun activateDesk(deskId: Int, transition: RemoteTransition?) = + @JvmOverloads + fun activateDesk( + deskId: Int, + transition: RemoteTransition?, + taskIdToReorderToFront: Int? = null, + ) = executeWithErrorLog({ "Failed call activateDesk" }) { - desktopMode?.activateDesk(deskId, transition) + desktopMode?.activateDesk(deskId, transition, taskIdToReorderToFront ?: INVALID_TASK_ID) } /** Calls shell to remove the desk whose ID is `deskId`. */ @@ -1124,10 +1132,23 @@ class SystemUiProxy @Inject constructor(@ApplicationContext private val context: fun removeAllDesks() = executeWithErrorLog({ "Failed call removeAllDesks" }) { desktopMode?.removeAllDesks() } - /** Call shell to show all apps active on the desktop */ - fun showDesktopApps(displayId: Int, transition: RemoteTransition?) = + /** + * Call shell to show all apps active on the desktop and bring [taskIdToReorderToFront] to front + * if it's valid on the default desk on the given display. If the provided + * [taskIdToReorderToFront]'s value is null, do not change the windows' activation on the desk. + */ + @JvmOverloads + fun showDesktopApps( + displayId: Int, + transition: RemoteTransition? = null, + taskIdToReorderToFront: Int? = null, + ) = executeWithErrorLog({ "Failed call showDesktopApps" }) { - desktopMode?.showDesktopApps(displayId, transition) + desktopMode?.showDesktopApps( + displayId, + transition, + taskIdToReorderToFront ?: INVALID_TASK_ID, + ) } /** If task with the given id is on the desktop, bring it to front */ diff --git a/quickstep/src/com/android/quickstep/TaskViewUtils.java b/quickstep/src/com/android/quickstep/TaskViewUtils.java index c4e204e5e5..47edb05928 100644 --- a/quickstep/src/com/android/quickstep/TaskViewUtils.java +++ b/quickstep/src/com/android/quickstep/TaskViewUtils.java @@ -678,6 +678,13 @@ public final class TaskViewUtils { // interfere with a rapid swipe up to home in the live tile + running task case. @Override public void onAnimationSuccess(Animator animation) { + // If we're relaunching the desktop tile when already entering Overview from + // desktop, no need to change the launcher visibility and taskbar visibility + // below. + boolean launchingLiveDesktop = v instanceof DesktopTaskView desktopTaskView + && desktopTaskView.isRunningTask() + && recentsView.getRemoteTargetHandles() != null; + recentsView.finishRecentsAnimation(false /* toRecents */, () -> { recentsView.post(() -> { stateManager.moveToRestState(); @@ -688,7 +695,7 @@ public final class TaskViewUtils { // that launcher is still visible. TaskbarUIController controller = recentsView.getSizeStrategy() .getTaskbarController(); - if (controller != null) { + if (controller != null && !launchingLiveDesktop) { boolean launcherVisible = true; for (RemoteAnimationTarget target : appTargets) { launcherVisible &= target.isTranslucent; diff --git a/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java b/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java index 0fb7b4331e..f80d209444 100644 --- a/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java +++ b/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java @@ -116,6 +116,7 @@ public class TaskViewSimulator implements TransformParams.BuilderProxy { private int mOrientationStateId; private SplitBounds mSplitBounds; private Boolean mDrawsBelowRecents = null; + private Boolean mDrawAboveOtherApps = null; private boolean mIsGridTask; private final boolean mIsDesktopTask; private boolean mIsAnimatingToCarousel = false; @@ -304,6 +305,15 @@ public class TaskViewSimulator implements TransformParams.BuilderProxy { mIsGridTask = isGridTask; } + /** + * Sets whether drawing this app above other apps during animation. It's currently used when + * activating an app window from the exploded desktop view which will launch the desktop tile + * and exit Overview. + */ + public void setDrawsAboveOtherApps(boolean drawsAboveOtherApps) { + mDrawAboveOtherApps = drawsAboveOtherApps; + } + /** * Apply translations on TaskRect's starting location. */ @@ -544,15 +554,22 @@ public class TaskViewSimulator implements TransformParams.BuilderProxy { .setWindowCrop(mTmpCropRect) .setCornerRadius(getCurrentCornerRadius()); - // If mDrawsBelowRecents is unset, no reordering will be enforced. - if (mDrawsBelowRecents != null) { - // In shell transitions, the animation leashes are reparented to an animation container - // so we can bump layers as needed. - builder.setLayer(mDrawsBelowRecents - // 1000 is an arbitrary number to give room for multiple layers. - ? Integer.MIN_VALUE + 1000 + app.prefixOrderIndex - mDesktopTaskIndex - : Integer.MAX_VALUE - 1000 + app.prefixOrderIndex - mDesktopTaskIndex); + if (mDrawsBelowRecents == null && mDrawAboveOtherApps == null) { + // No reordering will be enforced. + return; } + + // In shell transitions, the animation leashes are reparented to an animation container + // so we can bump layers as needed. + int baseLayer = app.prefixOrderIndex - mDesktopTaskIndex; + // 1000/2000 are arbitrary numbers to give room for multiple layers. + if (mDrawsBelowRecents != null) { + baseLayer += mDrawsBelowRecents ? Integer.MIN_VALUE + 2000 : Integer.MAX_VALUE - 2000; + } + if (mDrawAboveOtherApps != null && mDrawAboveOtherApps) { + baseLayer += 1000; + } + builder.setLayer(baseLayer); } /** diff --git a/quickstep/src/com/android/quickstep/views/DesktopTaskView.kt b/quickstep/src/com/android/quickstep/views/DesktopTaskView.kt index fe8a09cec2..dddc2ab023 100644 --- a/quickstep/src/com/android/quickstep/views/DesktopTaskView.kt +++ b/quickstep/src/com/android/quickstep/views/DesktopTaskView.kt @@ -402,6 +402,11 @@ class DesktopTaskView @JvmOverloads constructor(context: Context, attrs: Attribu } else { taskContentView } + if (enableDesktopExplodedView()) { + snapshotView.setOnClickListener { + launchTaskWithDesktopController(animated = true, task.key.id) + } + } TaskContainer( this, @@ -481,7 +486,15 @@ class DesktopTaskView @JvmOverloads constructor(context: Context, attrs: Attribu } } - private fun launchTaskWithDesktopController(animated: Boolean): RunnableList? { + /** + * Launches the desktop task and activate the task with [taskIdToReorderToFront] if it's + * provided and already on the desktop. It will exit Overview to desktop and activate the + * according new task afterwards if applicable. + */ + private fun launchTaskWithDesktopController( + animated: Boolean, + taskIdToReorderToFront: Int? = null, + ): RunnableList? { val recentsView = recentsView ?: return null TestLogging.recordEvent( TestProtocol.SEQUENCE_MAIN, @@ -492,8 +505,17 @@ class DesktopTaskView @JvmOverloads constructor(context: Context, attrs: Attribu val desktopController = recentsView.desktopRecentsController checkNotNull(desktopController) { "recentsController is null" } + if (taskIdToReorderToFront != null) { + // The to-be-activated window should animate on top of other apps during shell + // transition. + val remoteTargetHandle = getRemoteTargetHandle(taskIdToReorderToFront) + // The layer swapping is only applied after [createRecentsWindowAnimator] starts, which + // will bring the [remoteTargetHandles] above Recents, therefore this call won't affect + // the base surface in [DepthController]. + remoteTargetHandle?.taskViewSimulator?.setDrawsAboveOtherApps(true) + } val launchDesktopFromRecents = { - desktopController.launchDesktopFromRecents(this, animated) { + desktopController.launchDesktopFromRecents(this, animated, taskIdToReorderToFront) { endCallback.executeAllAndDestroy() } } diff --git a/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java b/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java index 4b338c6bac..6bfcf64f19 100644 --- a/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java +++ b/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java @@ -302,8 +302,7 @@ public class LauncherRecentsView extends RecentsView