From 65c04b0f0572a8021ed05103f35f8e8208a82038 Mon Sep 17 00:00:00 2001 From: Alex Chau Date: Mon, 17 Feb 2025 16:43:09 +0000 Subject: [PATCH] Fix live tile in dismiss and swipe down animation - Add separate property for grid translation in TaskViewSimulator, so it doesn't get reset when other translations (e.g. dismiss) is applied to live tile - In createAdjacentPageAnimForTaskLaunch, use onAnimationStart without isReverse parameter, so it's actually called when the PendingAniamtion starts - Also reset pivot if we have overriden it during createAdjacentPageAnimForTaskLaunch - Also avoid applying addOverviewToAppAnim on live tile if it's not launching, otherwise recentsViewScale will be applied twice with addOverviewToAppAnim applying wrong value - Use pivot instead of recentsViewScroll to bring non scroll position live tiel to fullscreen, to avoid a trajectory that will otherwise travel left and then right Fix: 391146807 Fix: 321013528 Test: launching via swipe down with non-launching live tile Test: dismissing live tile Test: launching live tile in non scroll position Flag: com.android.launcher3.enable_grid_only_overview Change-Id: I24ee85399b09b25e157a8986103658bb4803a87e --- .../com/android/quickstep/TaskViewUtils.java | 60 ++++++++++----- .../quickstep/util/TaskViewSimulator.java | 5 ++ .../android/quickstep/views/RecentsView.java | 76 +++++++++++++------ 3 files changed, 98 insertions(+), 43 deletions(-) diff --git a/quickstep/src/com/android/quickstep/TaskViewUtils.java b/quickstep/src/com/android/quickstep/TaskViewUtils.java index 35a6e72378..37c2d1c17b 100644 --- a/quickstep/src/com/android/quickstep/TaskViewUtils.java +++ b/quickstep/src/com/android/quickstep/TaskViewUtils.java @@ -38,6 +38,7 @@ import static com.android.launcher3.QuickstepTransitionManager.SPLIT_DIVIDER_ANI import static com.android.launcher3.QuickstepTransitionManager.SPLIT_LAUNCH_DURATION; import static com.android.launcher3.Utilities.getDescendantCoordRelativeToAncestor; import static com.android.launcher3.util.MultiPropertyFactory.MULTI_PROPERTY_VALUE; +import static com.android.quickstep.BaseContainerInterface.getTaskDimension; import static com.android.quickstep.util.AnimUtils.clampToDuration; import static com.android.wm.shell.shared.TransitionUtil.TYPE_SPLIT_SCREEN_DIM_LAYER; @@ -65,6 +66,7 @@ import androidx.annotation.Nullable; import com.android.app.animation.Interpolators; import com.android.internal.jank.Cuj; import com.android.launcher3.DeviceProfile; +import com.android.launcher3.Utilities; import com.android.launcher3.anim.AnimatedFloat; import com.android.launcher3.anim.AnimationSuccessListener; import com.android.launcher3.anim.AnimatorPlaybackController; @@ -102,6 +104,11 @@ public final class TaskViewUtils { private TaskViewUtils() {} + private static final Rect TEMP_THUMBNAIL_BOUNDS = new Rect(); + private static final Rect TEMP_FULLSCREEN_BOUNDS = new Rect(); + private static final PointF TEMP_TASK_DIMENSION = new PointF(); + private static final PointF TEMP_PIVOT = new PointF(); + /** * Try to find a TaskView that corresponds with the component of the launched view. * @@ -164,7 +171,7 @@ public final class TaskViewUtils { public static > void createRecentsWindowAnimator( @NonNull RecentsView recentsView, - @NonNull TaskView v, + @NonNull TaskView taskView, boolean skipViewChanges, @NonNull RemoteAnimationTarget[] appTargets, @NonNull RemoteAnimationTarget[] wallpaperTargets, @@ -172,31 +179,31 @@ public final class TaskViewUtils { @Nullable DepthController depthController, @Nullable TransitionInfo transitionInfo, PendingAnimation out) { - boolean isQuickSwitch = v.isEndQuickSwitchCuj(); - v.setEndQuickSwitchCuj(false); + boolean isQuickSwitch = taskView.isEndQuickSwitchCuj(); + taskView.setEndQuickSwitchCuj(false); final RemoteAnimationTargets targets = new RemoteAnimationTargets(appTargets, wallpaperTargets, nonAppTargets, MODE_OPENING); final RemoteAnimationTarget navBarTarget = targets.getNavBarRemoteAnimationTarget(); - SurfaceTransactionApplier applier = new SurfaceTransactionApplier(v); + SurfaceTransactionApplier applier = new SurfaceTransactionApplier(taskView); targets.addReleaseCheck(applier); RemoteTargetHandle[] remoteTargetHandles; RemoteTargetHandle[] recentsViewHandles = recentsView.getRemoteTargetHandles(); - if (v.isRunningTask() && recentsViewHandles != null) { + if (taskView.isRunningTask() && recentsViewHandles != null) { // Re-use existing handles remoteTargetHandles = recentsViewHandles; } else { - boolean forDesktop = v instanceof DesktopTaskView; - RemoteTargetGluer gluer = new RemoteTargetGluer(v.getContext(), + boolean forDesktop = taskView instanceof DesktopTaskView; + RemoteTargetGluer gluer = new RemoteTargetGluer(taskView.getContext(), recentsView.getSizeStrategy(), targets, forDesktop); if (forDesktop) { remoteTargetHandles = gluer.assignTargetsForDesktop(targets, transitionInfo); - } else if (v.containsMultipleTasks()) { + } else if (taskView.containsMultipleTasks()) { remoteTargetHandles = gluer.assignTargetsForSplitScreen(targets, - ((GroupedTaskView) v).getSplitBoundsConfig()); + ((GroupedTaskView) taskView).getSplitBoundsConfig()); } else { remoteTargetHandles = gluer.assignTargets(targets); } @@ -210,8 +217,8 @@ public final class TaskViewUtils { remoteTargetHandle.getTransformParams().setSyncTransactionApplier(applier); } - int taskIndex = recentsView.indexOfChild(v); - Context context = v.getContext(); + int taskIndex = recentsView.indexOfChild(taskView); + Context context = taskView.getContext(); T container = RecentsViewContainer.containerFromContext(context); DeviceProfile dp = container.getDeviceProfile(); @@ -219,11 +226,11 @@ public final class TaskViewUtils { boolean parallaxCenterAndAdjacentTask = !showAsGrid && taskIndex != recentsView.getCurrentPage(); int taskRectTranslationPrimary = recentsView.getScrollOffset(taskIndex); - int taskRectTranslationSecondary = showAsGrid ? (int) v.getGridTranslationY() : 0; + int taskRectTranslationSecondary = showAsGrid ? (int) taskView.getGridTranslationY() : 0; RemoteTargetHandle[] topMostSimulators = null; - if (!v.isRunningTask()) { + if (!taskView.isRunningTask()) { // TVSs already initialized from the running task, no need to re-init for (RemoteTargetHandle targetHandle : remoteTargetHandles) { TaskViewSimulator tvsLocal = targetHandle.getTaskViewSimulator(); @@ -237,13 +244,13 @@ public final class TaskViewUtils { tvsLocal.fullScreenProgress.value = 0; tvsLocal.recentsViewScale.value = 1; if (!enableGridOnlyOverview()) { - tvsLocal.setIsGridTask(v.isGridTask()); + tvsLocal.setIsGridTask(taskView.isGridTask()); } tvsLocal.getOrientationState().getOrientationHandler().set(tvsLocal, TaskViewSimulator::setTaskRectTranslation, taskRectTranslationPrimary, taskRectTranslationSecondary); - if (v instanceof DesktopTaskView) { + if (taskView instanceof DesktopTaskView) { targetHandle.getTransformParams().setTargetAlpha(1f); } else { // Fade in the task during the initial 20% of the animation @@ -260,8 +267,11 @@ public final class TaskViewUtils { out.setFloat(tvsLocal.recentsViewScale, AnimatedFloat.VALUE, tvsLocal.getFullScreenScale(), TOUCH_RESPONSE); - out.setFloat(tvsLocal.recentsViewScroll, AnimatedFloat.VALUE, 0, - TOUCH_RESPONSE); + if (!enableGridOnlyOverview()) { + out.setFloat(tvsLocal.recentsViewScroll, AnimatedFloat.VALUE, 0, + TOUCH_RESPONSE); + } + out.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationStart(Animator animation) { @@ -271,6 +281,18 @@ public final class TaskViewUtils { showTransaction.getTransaction().show(targets.apps[i].leash); } applier.scheduleApply(showTransaction); + + if (enableGridOnlyOverview()) { + taskView.getThumbnailBounds(TEMP_THUMBNAIL_BOUNDS, /*relativeToDragLayer=*/ + true); + getTaskDimension(context, container.getDeviceProfile(), + TEMP_TASK_DIMENSION); + TEMP_FULLSCREEN_BOUNDS.set(0, 0, (int) TEMP_TASK_DIMENSION.x, + (int) TEMP_TASK_DIMENSION.y); + Utilities.getPivotsForScalingRectToRect(TEMP_THUMBNAIL_BOUNDS, + TEMP_FULLSCREEN_BOUNDS, TEMP_PIVOT); + tvsLocal.setPivotOverride(TEMP_PIVOT); + } } }); out.addOnFrameCallback(() -> { @@ -321,7 +343,7 @@ public final class TaskViewUtils { if (!skipViewChanges && parallaxCenterAndAdjacentTask && topMostSimulators != null && topMostSimulators.length > 0) { - out.addFloat(v, VIEW_ALPHA, 1, 0, clampToProgress(LINEAR, 0.2f, 0.4f)); + out.addFloat(taskView, VIEW_ALPHA, 1, 0, clampToProgress(LINEAR, 0.2f, 0.4f)); RemoteTargetHandle[] simulatorCopies = topMostSimulators; for (RemoteTargetHandle handle : simulatorCopies) { @@ -340,7 +362,7 @@ public final class TaskViewUtils { // During animation we apply transformation on the thumbnailView (and not the rootView) // to follow the TaskViewSimulator. So the final matrix applied on the thumbnailView is: // Mt K(0)` K(t) Mt` - View[] thumbnails = v.getSnapshotViews(); + View[] thumbnails = taskView.getSnapshotViews(); // In case simulator copies and thumbnail size do no match, ensure we get the lesser. // This ensures we do not create arrays with empty elements or attempt to references diff --git a/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java b/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java index 09e9c8b119..b844079a14 100644 --- a/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java +++ b/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java @@ -97,6 +97,8 @@ public class TaskViewSimulator implements TransformParams.BuilderProxy { private final FullscreenDrawParams mCurrentFullscreenParams; public final AnimatedFloat taskPrimaryTranslation = new AnimatedFloat(); public final AnimatedFloat taskSecondaryTranslation = new AnimatedFloat(); + public final AnimatedFloat taskGridTranslationX = new AnimatedFloat(); + public final AnimatedFloat taskGridTranslationY = new AnimatedFloat(); // Carousel properties public final AnimatedFloat carouselScale = new AnimatedFloat(); @@ -445,6 +447,7 @@ public class TaskViewSimulator implements TransformParams.BuilderProxy { taskPrimaryTranslation.value); mOrientationState.getOrientationHandler().setSecondary(mMatrix, MATRIX_POST_TRANSLATE, taskSecondaryTranslation.value); + mMatrix.postTranslate(taskGridTranslationX.value, taskGridTranslationY.value); mMatrix.postScale(carouselScale.value, carouselScale.value, mIsRecentsRtl ? mCarouselTaskSize.right : mCarouselTaskSize.left, @@ -484,6 +487,8 @@ public class TaskViewSimulator implements TransformParams.BuilderProxy { + " taskRect: " + mTaskRect + " taskPrimaryT: " + taskPrimaryTranslation.value + " taskSecondaryT: " + taskSecondaryTranslation.value + + " taskGridTranslationX: " + taskGridTranslationX.value + + " taskGridTranslationY: " + taskGridTranslationY.value + " recentsPrimaryT: " + recentsViewPrimaryTranslation.value + " recentsSecondaryT: " + recentsViewSecondaryTranslation.value + " recentsScroll: " + recentsViewScroll.value diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java index 5bfcf43c18..d1d08ac8c8 100644 --- a/quickstep/src/com/android/quickstep/views/RecentsView.java +++ b/quickstep/src/com/android/quickstep/views/RecentsView.java @@ -2917,28 +2917,40 @@ public abstract class RecentsView< BaseState endState = mSizeStrategy.stateFromGestureEndTarget(endTarget); if (endState.displayOverviewTasksAsGrid(mContainer.getDeviceProfile())) { TaskView runningTaskView = getRunningTaskView(); - float runningTaskPrimaryGridTranslation = 0; - float runningTaskSecondaryGridTranslation = 0; + float runningTaskGridTranslationX = 0; + float runningTaskGridTranslationY = 0; if (runningTaskView != null) { // Apply the grid translation to running task unless it's being snapped to // and removes the current translation applied to the running task. - runningTaskPrimaryGridTranslation = runningTaskView.getGridTranslationX() + runningTaskGridTranslationX = runningTaskView.getGridTranslationX() - runningTaskView.getNonGridTranslationX(); - runningTaskSecondaryGridTranslation = runningTaskView.getGridTranslationY(); + runningTaskGridTranslationY = runningTaskView.getGridTranslationY(); } for (RemoteTargetHandle remoteTargetHandle : remoteTargetHandles) { TaskViewSimulator tvs = remoteTargetHandle.getTaskViewSimulator(); if (animatorSet == null) { setGridProgress(1); - tvs.taskPrimaryTranslation.value = runningTaskPrimaryGridTranslation; - tvs.taskSecondaryTranslation.value = runningTaskSecondaryGridTranslation; + if (enableGridOnlyOverview()) { + tvs.taskGridTranslationX.value = runningTaskGridTranslationX; + tvs.taskGridTranslationY.value = runningTaskGridTranslationY; + } else { + tvs.taskPrimaryTranslation.value = runningTaskGridTranslationX; + tvs.taskSecondaryTranslation.value = runningTaskGridTranslationY; + } } else { animatorSet.play(ObjectAnimator.ofFloat(this, RECENTS_GRID_PROGRESS, 1)); - animatorSet.play(tvs.carouselScale.animateToValue(1)); - animatorSet.play(tvs.taskPrimaryTranslation.animateToValue( - runningTaskPrimaryGridTranslation)); - animatorSet.play(tvs.taskSecondaryTranslation.animateToValue( - runningTaskSecondaryGridTranslation)); + if (enableGridOnlyOverview()) { + animatorSet.play(tvs.carouselScale.animateToValue(1)); + animatorSet.play(tvs.taskGridTranslationX.animateToValue( + runningTaskGridTranslationX)); + animatorSet.play(tvs.taskGridTranslationY.animateToValue( + runningTaskGridTranslationY)); + } else { + animatorSet.play(tvs.taskPrimaryTranslation.animateToValue( + runningTaskGridTranslationX)); + animatorSet.play(tvs.taskSecondaryTranslation.animateToValue( + runningTaskGridTranslationY)); + } } } } @@ -3491,8 +3503,13 @@ public abstract class RecentsView< final TaskView runningTask = getRunningTaskView(); if (showAsGrid() && enableGridOnlyOverview() && runningTask != null) { runActionOnRemoteHandles( - remoteTargetHandle -> remoteTargetHandle.getTaskViewSimulator() - .taskSecondaryTranslation.value = runningTask.getGridTranslationY() + remoteTargetHandle -> { + remoteTargetHandle.getTaskViewSimulator().taskGridTranslationX.value = + runningTask.getGridTranslationX() + - runningTask.getNonGridTranslationX(); + remoteTargetHandle.getTaskViewSimulator().taskGridTranslationY.value = + runningTask.getGridTranslationY(); + } ); } @@ -3606,12 +3623,9 @@ public abstract class RecentsView< if (taskView.isRunningTask()) { anim.addOnFrameCallback(() -> { if (!mEnableDrawingLiveTile) return; - runActionOnRemoteHandles( - remoteTargetHandle -> remoteTargetHandle.getTaskViewSimulator() - .taskSecondaryTranslation.value = getPagedOrientationHandler() - .getSecondaryValue(taskView.getTranslationX(), - taskView.getTranslationY() - )); + runActionOnRemoteHandles(remoteTargetHandle -> + remoteTargetHandle.getTaskViewSimulator().taskSecondaryTranslation.value = + taskView.getSecondaryDismissTranslationProperty().get(taskView)); redrawLiveTile(); }); } @@ -5655,7 +5669,7 @@ public abstract class RecentsView< anim.play(ObjectAnimator.ofFloat(this, FULLSCREEN_PROGRESS, 1)); anim.addListener(new AnimatorListenerAdapter() { @Override - public void onAnimationStart(@NonNull Animator animation, boolean isReverse) { + public void onAnimationStart(@NonNull Animator animation) { taskView.getThumbnailBounds(mTempRect, /*relativeToDragLayer=*/true); getTaskDimension(mContext, mContainer.getDeviceProfile(), mTempPointF); Rect fullscreenBounds = new Rect(0, 0, (int) mTempPointF.x, @@ -5677,6 +5691,18 @@ public abstract class RecentsView< }); } } + + @Override + public void onAnimationEnd(Animator animation) { + // If live tile is not launching, reset the pivot applied above. + if (!taskView.isRunningTask()) { + runActionOnRemoteHandles( + remoteTargetHandle -> { + remoteTargetHandle.getTaskViewSimulator().setPivotOverride( + null); + }); + } + } }); } else if (!showAsGrid) { // We are launching an adjacent task, so parallax the center and other adjacent task. @@ -5785,10 +5811,12 @@ public abstract class RecentsView< mPendingAnimation = new PendingAnimation(duration); mPendingAnimation.add(anim); - runActionOnRemoteHandles( - remoteTargetHandle -> remoteTargetHandle.getTaskViewSimulator() - .addOverviewToAppAnim(mPendingAnimation, interpolator)); - mPendingAnimation.addOnFrameCallback(this::redrawLiveTile); + if (taskView.isRunningTask()) { + runActionOnRemoteHandles( + remoteTargetHandle -> remoteTargetHandle.getTaskViewSimulator() + .addOverviewToAppAnim(mPendingAnimation, interpolator)); + mPendingAnimation.addOnFrameCallback(this::redrawLiveTile); + } mPendingAnimation.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationStart(Animator animation) {