Using TaskViewSimulator for animating task launch
Bug: 155816922
Bug: 156398988
Change-Id: I8d64322596e9d99df49b01cb9adfbfca6d95b89b
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java
index c037e44..38adf39 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java
@@ -19,8 +19,8 @@
import static com.android.launcher3.LauncherState.NORMAL;
import static com.android.launcher3.anim.Interpolators.AGGRESSIVE_EASE;
import static com.android.launcher3.anim.Interpolators.LINEAR;
+import static com.android.quickstep.TaskViewUtils.createRecentsWindowAnimator;
import static com.android.quickstep.TaskViewUtils.findTaskViewToLaunch;
-import static com.android.quickstep.TaskViewUtils.getRecentsWindowAnimator;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
@@ -34,6 +34,7 @@
import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.anim.Interpolators;
+import com.android.launcher3.anim.PendingAnimation;
import com.android.quickstep.views.RecentsView;
import com.android.quickstep.views.TaskView;
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
@@ -63,9 +64,10 @@
boolean skipLauncherChanges = !launcherClosing;
TaskView taskView = findTaskViewToLaunch(mLauncher, v, appTargets);
- Animator recentsAnimator = getRecentsWindowAnimator(taskView, skipLauncherChanges,
- appTargets, wallpaperTargets, mLauncher.getDepthController());
- anim.play(recentsAnimator.setDuration(RECENTS_LAUNCH_DURATION));
+ PendingAnimation pa = new PendingAnimation(RECENTS_LAUNCH_DURATION);
+ createRecentsWindowAnimator(taskView, skipLauncherChanges, appTargets, wallpaperTargets,
+ mLauncher.getDepthController(), pa);
+ anim.play(pa.buildAnim());
Animator childStateAnimation = null;
// Found a visible recents task that matches the opening app, lets launch the app from there
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/RecentsActivity.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/RecentsActivity.java
index 33b7f12..b441490 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/RecentsActivity.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/RecentsActivity.java
@@ -23,7 +23,7 @@
import static com.android.launcher3.QuickstepAppTransitionManagerImpl.STATUS_BAR_TRANSITION_PRE_DELAY;
import static com.android.launcher3.testing.TestProtocol.OVERVIEW_STATE_ORDINAL;
import static com.android.quickstep.TaskUtils.taskIsATargetWithMode;
-import static com.android.quickstep.TaskViewUtils.getRecentsWindowAnimator;
+import static com.android.quickstep.TaskViewUtils.createRecentsWindowAnimator;
import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_CLOSING;
import android.animation.Animator;
@@ -44,6 +44,7 @@
import com.android.launcher3.LauncherAnimationRunner;
import com.android.launcher3.R;
import com.android.launcher3.anim.Interpolators;
+import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.compat.AccessibilityManagerCompat;
import com.android.launcher3.statemanager.StateManager;
import com.android.launcher3.statemanager.StateManager.AtomicAnimationFactory;
@@ -225,9 +226,10 @@
RemoteAnimationTargetCompat[] wallpaperTargets) {
AnimatorSet target = new AnimatorSet();
boolean activityClosing = taskIsATargetWithMode(appTargets, getTaskId(), MODE_CLOSING);
- Animator recentsAnimator = getRecentsWindowAnimator(taskView, !activityClosing, appTargets,
- wallpaperTargets, null /* depthController */);
- target.play(recentsAnimator.setDuration(RECENTS_LAUNCH_DURATION));
+ PendingAnimation pa = new PendingAnimation(RECENTS_LAUNCH_DURATION);
+ createRecentsWindowAnimator(taskView, !activityClosing, appTargets,
+ wallpaperTargets, null /* depthController */, pa);
+ target.play(pa.buildAnim());
// Found a visible recents task that matches the opening app, lets launch the app from there
if (activityClosing) {
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskViewUtils.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskViewUtils.java
index 9a7a491..c81afac 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskViewUtils.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskViewUtils.java
@@ -15,44 +15,46 @@
*/
package com.android.quickstep;
+import static com.android.launcher3.LauncherAnimUtils.VIEW_ALPHA;
import static com.android.launcher3.LauncherState.BACKGROUND_APP;
+import static com.android.launcher3.Utilities.getDescendantCoordRelativeToAncestor;
import static com.android.launcher3.anim.Interpolators.LINEAR;
import static com.android.launcher3.anim.Interpolators.TOUCH_RESPONSE_INTERPOLATOR;
-import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
+import static com.android.launcher3.anim.Interpolators.clampToProgress;
import static com.android.launcher3.statehandlers.DepthController.DEPTH;
import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_OPENING;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
-import android.animation.AnimatorSet;
-import android.animation.ObjectAnimator;
-import android.animation.ValueAnimator;
+import android.annotation.TargetApi;
import android.content.ComponentName;
+import android.content.Context;
+import android.graphics.Matrix;
+import android.graphics.Matrix.ScaleToFit;
import android.graphics.RectF;
+import android.os.Build;
import android.view.View;
import com.android.launcher3.BaseActivity;
import com.android.launcher3.BaseDraggingActivity;
-import com.android.launcher3.Utilities;
+import com.android.launcher3.DeviceProfile;
+import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.statehandlers.DepthController;
-import com.android.quickstep.util.AppWindowAnimationHelper;
-import com.android.quickstep.util.MultiValueUpdateListener;
+import com.android.launcher3.util.DefaultDisplay;
+import com.android.quickstep.util.TaskViewSimulator;
import com.android.quickstep.util.TransformParams;
import com.android.quickstep.views.RecentsView;
+import com.android.quickstep.views.TaskThumbnailView;
import com.android.quickstep.views.TaskView;
import com.android.systemui.shared.recents.model.Task;
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat;
-import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat.SurfaceParams;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
/**
* Utility class for helpful methods related to {@link TaskView} objects and their tasks.
*/
+@TargetApi(Build.VERSION_CODES.R)
public final class TaskViewUtils {
private TaskViewUtils() {}
@@ -118,97 +120,116 @@
}
/**
- * @return Animator that controls the window of the opening targets for the recents launch
+ * Creates an animation that controls the window of the opening targets for the recents launch
* animation.
*/
- public static Animator getRecentsWindowAnimator(TaskView v, boolean skipViewChanges,
+ public static void createRecentsWindowAnimator(TaskView v, boolean skipViewChanges,
RemoteAnimationTargetCompat[] appTargets,
- RemoteAnimationTargetCompat[] wallpaperTargets,
- DepthController depthController) {
- AppWindowAnimationHelper inOutHelper = new AppWindowAnimationHelper(
- v.getRecentsView().getPagedViewOrientedState(), v.getContext());
+ RemoteAnimationTargetCompat[] wallpaperTargets, DepthController depthController,
+ PendingAnimation out) {
SyncRtSurfaceTransactionApplierCompat applier =
new SyncRtSurfaceTransactionApplierCompat(v);
final RemoteAnimationTargets targets =
new RemoteAnimationTargets(appTargets, wallpaperTargets, MODE_OPENING);
targets.addDependentTransactionApplier(applier);
- TransformParams params =
- new TransformParams()
+
+ TransformParams params = new TransformParams()
.setSyncTransactionApplier(applier)
.setTargetSet(targets);
- AnimatorSet animatorSet = new AnimatorSet();
final RecentsView recentsView = v.getRecentsView();
- final ValueAnimator appAnimator = ValueAnimator.ofFloat(0, 1);
- appAnimator.setInterpolator(TOUCH_RESPONSE_INTERPOLATOR);
- appAnimator.addUpdateListener(new MultiValueUpdateListener() {
+ int taskIndex = recentsView.indexOfChild(v);
+ boolean parallaxCenterAndAdjacentTask = taskIndex != recentsView.getCurrentPage();
+ int startScroll = recentsView.getScrollOffset(taskIndex);
- // Defer fading out the view until after the app window gets faded in
- final FloatProp mViewAlpha = new FloatProp(1f, 0f, 75, 75, LINEAR);
- final FloatProp mTaskAlpha = new FloatProp(0f, 1f, 0, 75, LINEAR);
- final RectF mThumbnailRect;
+ params.setProgress(1);
+ out.setFloat(params, TransformParams.PROGRESS, 0, TOUCH_RESPONSE_INTERPOLATOR);
- {
- params.setTaskAlphaCallback((t, alpha) -> mTaskAlpha.value);
- inOutHelper.prepareAnimation(
- BaseActivity.fromContext(v.getContext()).getDeviceProfile());
- inOutHelper.fromTaskThumbnailView(v.getThumbnail(), (RecentsView) v.getParent(),
- targets.apps.length == 0 ? null : targets.apps[0]);
+ Context context = v.getContext();
+ DeviceProfile dp = BaseActivity.fromContext(context).getDeviceProfile();
+ // RecentsView never updates the display rotation until swipe-up so the value may be stale.
+ // Use the display value instead.
+ int displayRotation = DefaultDisplay.INSTANCE.get(context).getInfo().rotation;
- mThumbnailRect = new RectF(inOutHelper.getTargetRect());
- mThumbnailRect.offset(-v.getTranslationX(), -v.getTranslationY());
- Utilities.scaleRectFAboutCenter(mThumbnailRect, 1 / v.getScaleX());
- }
+ TaskViewSimulator topMostSimulator = null;
+ if (targets.apps.length > 0) {
+ TaskViewSimulator tsv = new TaskViewSimulator(context, recentsView.getSizeStrategy());
+ tsv.setDp(dp);
+ tsv.setLayoutRotation(displayRotation, displayRotation);
+ tsv.setPreview(targets.apps[targets.apps.length - 1]);
+ tsv.fullScreenProgress.value = 0;
+ tsv.recentsViewScale.value = 1;
+ tsv.setScroll(startScroll);
- @Override
- public void onUpdate(float percent) {
- // TODO: Take into account the current fullscreen progress for animating the insets
- params.setProgress(1 - percent);
- RectF taskBounds;
- if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
- List<SurfaceParams> surfaceParamsList = new ArrayList<>();
- // Append the surface transform params for the app that's being opened.
- Collections.addAll(surfaceParamsList, inOutHelper.computeSurfaceParams(params));
+ out.setFloat(tsv.fullScreenProgress,
+ AnimatedFloat.VALUE, 1, TOUCH_RESPONSE_INTERPOLATOR);
+ out.setFloat(tsv.recentsViewScale,
+ AnimatedFloat.VALUE, tsv.getFullScreenScale(), TOUCH_RESPONSE_INTERPOLATOR);
+ out.setInt(tsv, TaskViewSimulator.SCROLL, 0, TOUCH_RESPONSE_INTERPOLATOR);
- AppWindowAnimationHelper liveTileAnimationHelper =
- v.getRecentsView().getClipAnimationHelper();
- if (liveTileAnimationHelper != null) {
- // Append the surface transform params for the live tile app.
- TransformParams liveTileParams =
- v.getRecentsView().getLiveTileParams(true /* mightNeedToRefill */);
- if (liveTileParams != null) {
- SurfaceParams[] liveTileSurfaceParams =
- liveTileAnimationHelper.computeSurfaceParams(liveTileParams);
- if (liveTileSurfaceParams != null) {
- Collections.addAll(surfaceParamsList, liveTileSurfaceParams);
- }
- }
- }
- // Apply surface transform using the surface params list.
- params.applySurfaceParams(
- surfaceParamsList.toArray(new SurfaceParams[surfaceParamsList.size()]));
- // Get the task bounds for the app that's being opened after surface transform
- // update.
- taskBounds = inOutHelper.updateCurrentRect(params);
- } else {
- taskBounds = inOutHelper.applyTransform(params);
+ out.addOnFrameCallback(() -> tsv.apply(params));
+ topMostSimulator = tsv;
+ }
+
+ // Fade in the task during the initial 20% of the animation
+ AnimatedFloat taskAlpha = new AnimatedFloat(() -> { });
+ params.setTaskAlphaCallback((t, alpha) -> taskAlpha.value);
+ out.addFloat(taskAlpha, AnimatedFloat.VALUE, 0, 1, clampToProgress(LINEAR, 0, 0.2f));
+
+ if (!skipViewChanges && parallaxCenterAndAdjacentTask && topMostSimulator != null) {
+ out.addFloat(v, VIEW_ALPHA, 1, 0, clampToProgress(LINEAR, 0.2f, 0.4f));
+
+ TaskViewSimulator simulatorToCopy = topMostSimulator;
+ simulatorToCopy.apply(params);
+
+ // Mt represents the overall transformation on the thumbnailView relative to the
+ // Launcher's rootView
+ // K(t) represents transformation on the running window by the taskViewSimulator at
+ // any time t.
+ // at t = 0, we know that the simulator matches the thumbnailView. So if we apply K(0)`
+ // on the Launcher's rootView, the thumbnailView would match the full running task
+ // window. If we apply "K(0)` K(t)" thumbnailView will match the final transformed
+ // window at any time t. This gives the overall matrix on thumbnailView to be:
+ // Mt K(0)` K(t)
+ // 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`
+ TaskThumbnailView ttv = v.getThumbnail();
+ RectF tvBounds = new RectF(0, 0, ttv.getWidth(), ttv.getHeight());
+ float[] tvBoundsMapped = new float[]{0, 0, ttv.getWidth(), ttv.getHeight()};
+ getDescendantCoordRelativeToAncestor(ttv, ttv.getRootView(), tvBoundsMapped, false);
+ RectF tvBoundsInRoot = new RectF(
+ tvBoundsMapped[0], tvBoundsMapped[1],
+ tvBoundsMapped[2], tvBoundsMapped[3]);
+
+ Matrix mt = new Matrix();
+ mt.setRectToRect(tvBounds, tvBoundsInRoot, ScaleToFit.FILL);
+
+ Matrix mti = new Matrix();
+ mt.invert(mti);
+
+ Matrix k0i = new Matrix();
+ simulatorToCopy.getCurrentMatrix().invert(k0i);
+
+ Matrix animationMatrix = new Matrix();
+ out.addOnFrameCallback(() -> {
+ animationMatrix.set(mt);
+ animationMatrix.postConcat(k0i);
+ animationMatrix.postConcat(simulatorToCopy.getCurrentMatrix());
+ animationMatrix.postConcat(mti);
+ ttv.setAnimationMatrix(animationMatrix);
+ });
+
+ out.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ ttv.setAnimationMatrix(null);
}
+ });
+ }
- int taskIndex = recentsView.indexOfChild(v);
- int centerTaskIndex = recentsView.getCurrentPage();
- boolean parallaxCenterAndAdjacentTask = taskIndex != centerTaskIndex;
- if (!skipViewChanges && parallaxCenterAndAdjacentTask) {
- float scale = taskBounds.width() / mThumbnailRect.width();
- v.setScaleX(scale);
- v.setScaleY(scale);
- v.setTranslationX(taskBounds.centerX() - mThumbnailRect.centerX());
- v.setTranslationY(taskBounds.centerY() - mThumbnailRect.centerY());
- v.setAlpha(mViewAlpha.value);
- }
- }
- });
- appAnimator.addListener(new AnimatorListenerAdapter() {
+ out.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
targets.release();
@@ -216,12 +237,8 @@
});
if (depthController != null) {
- ObjectAnimator backgroundRadiusAnim = ObjectAnimator.ofFloat(depthController,
- DEPTH, BACKGROUND_APP.getDepth(v.getContext()));
- animatorSet.playTogether(appAnimator, backgroundRadiusAnim);
- } else {
- animatorSet.play(appAnimator);
+ out.setFloat(depthController, DEPTH, BACKGROUND_APP.getDepth(context),
+ TOUCH_RESPONSE_INTERPOLATOR);
}
- return animatorSet;
}
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/AppWindowAnimationHelper.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/AppWindowAnimationHelper.java
deleted file mode 100644
index b743d3f..0000000
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/AppWindowAnimationHelper.java
+++ /dev/null
@@ -1,294 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.quickstep.util;
-
-import static com.android.launcher3.Utilities.boundToRange;
-import static com.android.launcher3.Utilities.mapRange;
-import static com.android.systemui.shared.system.QuickStepContract.getWindowCornerRadius;
-import static com.android.systemui.shared.system.QuickStepContract.supportsRoundedCornersOnWindows;
-
-import android.annotation.TargetApi;
-import android.content.Context;
-import android.content.res.Resources;
-import android.graphics.Matrix;
-import android.graphics.Matrix.ScaleToFit;
-import android.graphics.Rect;
-import android.graphics.RectF;
-import android.os.Build;
-
-import androidx.annotation.Nullable;
-
-import com.android.launcher3.BaseDraggingActivity;
-import com.android.launcher3.DeviceProfile;
-import com.android.launcher3.R;
-import com.android.launcher3.Utilities;
-import com.android.launcher3.views.BaseDragLayer;
-import com.android.quickstep.SystemUiProxy;
-import com.android.quickstep.views.RecentsView;
-import com.android.quickstep.views.TaskThumbnailView;
-import com.android.systemui.shared.recents.utilities.RectFEvaluator;
-import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
-import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat;
-import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat.SurfaceParams;
-import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat.SurfaceParams.Builder;
-import com.android.systemui.shared.system.WindowManagerWrapper;
-
-/**
- * Utility class to handle window clip animation
- */
-@TargetApi(Build.VERSION_CODES.P)
-public class AppWindowAnimationHelper implements TransformParams.BuilderProxy {
-
- // The bounds of the source app in device coordinates
- private final RectF mSourceStackBounds = new RectF();
- // The insets of the source app
- private final Rect mSourceInsets = new Rect();
- // The source app bounds with the source insets applied, in the device coordinates
- private final RectF mSourceRect = new RectF();
- // The bounds of the task view in device coordinates
- private final RectF mTargetRect = new RectF();
- // The bounds of the app window (between mSourceRect and mTargetRect) in device coordinates
- private final RectF mCurrentRect = new RectF();
- // The insets to be used for clipping the app window, which can be larger than mSourceInsets
- // if the aspect ratio of the target is smaller than the aspect ratio of the source rect. In
- // app window coordinates.
- private final RectF mSourceWindowClipInsets = new RectF();
- // The clip rect in source app window coordinates. The app window surface will only be drawn
- // within these bounds. This clip rect starts at the full mSourceStackBounds, and insets by
- // mSourceWindowClipInsets as the transform progress goes to 1.
- private final RectF mCurrentClipRectF = new RectF();
-
- // The bounds of launcher (not including insets) in device coordinates
- public final Rect mHomeStackBounds = new Rect();
- private final RectFEvaluator mRectFEvaluator = new RectFEvaluator();
- private final Matrix mTmpMatrix = new Matrix();
- private final Rect mTmpRect = new Rect();
- private final RectF mTmpRectF = new RectF();
- private RecentsOrientedState mOrientedState;
- // Corner radius of windows, in pixels
- private final float mWindowCornerRadius;
- // Corner radius of windows when they're in overview mode.
- private final float mTaskCornerRadius;
- // If windows can have real time rounded corners.
- private final boolean mSupportsRoundedCornersOnWindows;
- // Whether or not to actually use the rounded cornders on windows
- private boolean mUseRoundedCornersOnWindows;
-
- public AppWindowAnimationHelper(RecentsOrientedState orientedState, Context context) {
- Resources res = context.getResources();
- mOrientedState = orientedState;
- mWindowCornerRadius = getWindowCornerRadius(res);
- mSupportsRoundedCornersOnWindows = supportsRoundedCornersOnWindows(res);
- mTaskCornerRadius = TaskCornerRadius.get(context);
- mUseRoundedCornersOnWindows = mSupportsRoundedCornersOnWindows;
- }
-
- private void updateSourceStack(RemoteAnimationTargetCompat target) {
- mSourceInsets.set(target.contentInsets);
- mSourceStackBounds.set(target.screenSpaceBounds);
- }
-
- public void updateTargetRect(Rect targetRect) {
- mSourceRect.set(mSourceInsets.left, mSourceInsets.top,
- mSourceStackBounds.width() - mSourceInsets.right,
- mSourceStackBounds.height() - mSourceInsets.bottom);
- mTargetRect.set(targetRect);
- mTargetRect.offset(mHomeStackBounds.left - mSourceStackBounds.left,
- mHomeStackBounds.top - mSourceStackBounds.top);
-
- // Calculate the clip based on the target rect (since the content insets and the
- // launcher insets may differ, so the aspect ratio of the target rect can differ
- // from the source rect. The difference between the target rect (scaled to the
- // source rect) is the amount to clip on each edge.
- RectF scaledTargetRect = new RectF(mTargetRect);
- float scale = getSrcToTargetScale();
- Utilities.scaleRectFAboutCenter(scaledTargetRect, scale);
-
- scaledTargetRect.offsetTo(mSourceRect.left, mSourceRect.top);
- mSourceWindowClipInsets.set(
- Math.max(scaledTargetRect.left, 0),
- Math.max(scaledTargetRect.top, 0),
- Math.max(mSourceStackBounds.width() - scaledTargetRect.right, 0),
- Math.max(mSourceStackBounds.height() - scaledTargetRect.bottom, 0));
- mSourceRect.set(scaledTargetRect);
- }
-
- public float getSrcToTargetScale() {
- return LayoutUtils.getTaskScale(mOrientedState,
- mSourceRect.width(), mSourceRect.height(),
- mTargetRect.width(), mTargetRect.height());
- }
-
- public void prepareAnimation(DeviceProfile dp) {
- mUseRoundedCornersOnWindows = mSupportsRoundedCornersOnWindows && !dp.isMultiWindowMode;
- }
-
- public RectF applyTransform(TransformParams params) {
- SurfaceParams[] surfaceParams = computeSurfaceParams(params);
- if (surfaceParams == null) {
- return null;
- }
- params.applySurfaceParams(surfaceParams);
- return mCurrentRect;
- }
-
- /**
- * Updates this AppWindowAnimationHelper's state based on the given TransformParams, and returns
- * the SurfaceParams to apply via {@link SyncRtSurfaceTransactionApplierCompat#applyParams}.
- */
- public SurfaceParams[] computeSurfaceParams(TransformParams params) {
- if (params.getTargetSet() == null) {
- return null;
- }
-
- updateCurrentRect(params);
- return params.createSurfaceParams(this);
- }
-
- @Override
- public void onBuildParams(Builder builder, RemoteAnimationTargetCompat app,
- int targetMode, TransformParams params) {
- Rect crop = mTmpRect;
- crop.set(app.screenSpaceBounds);
- crop.offsetTo(0, 0);
- float cornerRadius = 0f;
- float scale = Math.max(mCurrentRect.width(), mTargetRect.width()) / crop.width();
- mTmpMatrix.setTranslate(0, 0);
- if (app.activityType == RemoteAnimationTargetCompat.ACTIVITY_TYPE_HOME) {
- mTmpMatrix.setTranslate(app.localBounds.left, app.localBounds.top);
- }
- if (app.mode == targetMode
- && app.activityType != RemoteAnimationTargetCompat.ACTIVITY_TYPE_HOME) {
- mTmpMatrix.setRectToRect(mSourceRect, mCurrentRect, ScaleToFit.FILL);
- mTmpMatrix.postTranslate(app.localBounds.left, app.localBounds.top);
- mCurrentClipRectF.roundOut(crop);
- if (mSupportsRoundedCornersOnWindows) {
- if (params.getCornerRadius() > -1) {
- cornerRadius = params.getCornerRadius();
- scale = mCurrentRect.width() / crop.width();
- } else {
- float windowCornerRadius = mUseRoundedCornersOnWindows
- ? mWindowCornerRadius : 0;
- cornerRadius = mapRange(boundToRange(params.getProgress(), 0, 1),
- windowCornerRadius, mTaskCornerRadius);
- }
- }
-
- builder.withMatrix(mTmpMatrix)
- .withWindowCrop(crop)
- // Since radius is in Surface space, but we draw the rounded corners in screen
- // space, we have to undo the scale
- .withCornerRadius(cornerRadius / scale);
-
- }
- }
-
- public RectF updateCurrentRect(TransformParams params) {
- if (params.getCurrentRect() != null) {
- mCurrentRect.set(params.getCurrentRect());
- } else {
- mTmpRectF.set(mTargetRect);
- mCurrentRect.set(mRectFEvaluator.evaluate(
- params.getProgress(), mSourceRect, mTmpRectF));
- }
-
- updateClipRect(params);
- return mCurrentRect;
- }
-
- private void updateClipRect(TransformParams params) {
- // Don't clip past progress > 1.
- float progress = Math.min(1, params.getProgress());
- mCurrentClipRectF.left = mSourceWindowClipInsets.left * progress;
- mCurrentClipRectF.top = mSourceWindowClipInsets.top * progress;
- mCurrentClipRectF.right =
- mSourceStackBounds.width() - (mSourceWindowClipInsets.right * progress);
- mCurrentClipRectF.bottom =
- mSourceStackBounds.height() - (mSourceWindowClipInsets.bottom * progress);
- }
-
- public void fromTaskThumbnailView(TaskThumbnailView ttv, RecentsView rv,
- @Nullable RemoteAnimationTargetCompat target) {
- BaseDraggingActivity activity = BaseDraggingActivity.fromContext(ttv.getContext());
- BaseDragLayer dl = activity.getDragLayer();
-
- int[] pos = new int[2];
- dl.getLocationOnScreen(pos);
- mHomeStackBounds.set(0, 0, dl.getWidth(), dl.getHeight());
- mHomeStackBounds.offset(pos[0], pos[1]);
-
- if (target != null) {
- updateSourceStack(target);
- } else if (rv.shouldUseMultiWindowTaskSizeStrategy()) {
- updateStackBoundsToMultiWindowTaskSize(activity);
- } else {
- mSourceStackBounds.set(mHomeStackBounds);
- Rect fallback = dl.getInsets();
- mSourceInsets.set(ttv.getInsets(fallback));
- }
-
- Rect targetRect = new Rect();
- dl.getDescendantRectRelativeToSelf(ttv, targetRect);
- updateTargetRect(targetRect);
-
- if (target == null) {
- // Transform the clip relative to the target rect. Only do this in the case where we
- // aren't applying the insets to the app windows (where the clip should be in target app
- // space)
- float scale = mTargetRect.width() / mSourceRect.width();
- mSourceWindowClipInsets.left = mSourceWindowClipInsets.left * scale;
- mSourceWindowClipInsets.top = mSourceWindowClipInsets.top * scale;
- mSourceWindowClipInsets.right = mSourceWindowClipInsets.right * scale;
- mSourceWindowClipInsets.bottom = mSourceWindowClipInsets.bottom * scale;
- }
- }
-
- private void updateStackBoundsToMultiWindowTaskSize(BaseDraggingActivity activity) {
- SystemUiProxy proxy = SystemUiProxy.INSTANCE.get(activity);
- if (proxy.isActive()) {
- mSourceStackBounds.set(proxy.getNonMinimizedSplitScreenSecondaryBounds());
- return;
- }
-
- // Assume that the task size is half screen size (minus the insets and the divider size)
- DeviceProfile fullDp = activity.getDeviceProfile().getFullScreenProfile();
- // Use availableWidthPx and availableHeightPx instead of widthPx and heightPx to
- // account for system insets
- int taskWidth = fullDp.availableWidthPx;
- int taskHeight = fullDp.availableHeightPx;
- int halfDividerSize = activity.getResources()
- .getDimensionPixelSize(R.dimen.multi_window_task_divider_size) / 2;
-
- Rect insets = new Rect();
- WindowManagerWrapper.getInstance().getStableInsets(insets);
- if (fullDp.isLandscape) {
- taskWidth = taskWidth / 2 - halfDividerSize;
- } else {
- taskHeight = taskHeight / 2 - halfDividerSize;
- }
-
- // Align the task to bottom left/right edge (closer to nav bar).
- int left = activity.getDeviceProfile().isSeascape() ? insets.left
- : (insets.left + fullDp.availableWidthPx - taskWidth);
- mSourceStackBounds.set(0, 0, taskWidth, taskHeight);
- mSourceStackBounds.offset(left, insets.top + fullDp.availableHeightPx - taskHeight);
- }
-
- public RectF getTargetRect() {
- return mTargetRect;
- }
-
-}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/TaskViewSimulator.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/TaskViewSimulator.java
index 348c22d..4e1d849 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/TaskViewSimulator.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/TaskViewSimulator.java
@@ -26,6 +26,7 @@
import android.graphics.PointF;
import android.graphics.Rect;
import android.graphics.RectF;
+import android.util.IntProperty;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.R;
@@ -47,6 +48,19 @@
*/
public class TaskViewSimulator implements TransformParams.BuilderProxy {
+ public static final IntProperty<TaskViewSimulator> SCROLL =
+ new IntProperty<TaskViewSimulator>("scroll") {
+ @Override
+ public void setValue(TaskViewSimulator simulator, int i) {
+ simulator.setScroll(i);
+ }
+
+ @Override
+ public Integer get(TaskViewSimulator simulator) {
+ return simulator.mScrollState.scroll;
+ }
+ };
+
private final Rect mTmpCropRect = new Rect();
private final RectF mTempRectF = new RectF();
private final float[] mTempPoint = new float[2];
@@ -279,4 +293,5 @@
// Ideally we should use square-root. This is an optimization as one of the dimension is 0.
return Math.max(Math.abs(mTempPoint[0]), Math.abs(mTempPoint[1]));
}
+
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/TransformParams.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/TransformParams.java
index d837e54..b929f26 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/TransformParams.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/TransformParams.java
@@ -15,11 +15,8 @@
*/
package com.android.quickstep.util;
-import android.graphics.RectF;
import android.util.FloatProperty;
-import androidx.annotation.Nullable;
-
import com.android.launcher3.Utilities;
import com.android.launcher3.anim.Interpolators;
import com.android.quickstep.RemoteAnimationTargets;
@@ -44,7 +41,6 @@
};
private float mProgress;
- private @Nullable RectF mCurrentRect;
private float mTargetAlpha;
private float mCornerRadius;
private RemoteAnimationTargets mTargetSet;
@@ -55,7 +51,6 @@
public TransformParams() {
mProgress = 0;
- mCurrentRect = null;
mTargetAlpha = 1;
mCornerRadius = -1;
}
@@ -81,17 +76,6 @@
}
/**
- * Sets the current rect to show the transformed window, in device coordinates. This gives
- * the caller manual control of where to show the window. If unspecified (null), we
- * interpolate between {@link AppWindowAnimationHelper#mSourceRect} and
- * {@link AppWindowAnimationHelper#mTargetRect}, based on {@link #mProgress}.
- */
- public TransformParams setCurrentRect(RectF currentRect) {
- mCurrentRect = currentRect;
- return this;
- }
-
- /**
* Specifies the alpha of the transformed window. Default is 1.
*/
public TransformParams setTargetAlpha(float targetAlpha) {
@@ -173,11 +157,6 @@
return mProgress;
}
- @Nullable
- public RectF getCurrentRect() {
- return mCurrentRect;
- }
-
public float getTargetAlpha() {
return mTargetAlpha;
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/LauncherRecentsView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/LauncherRecentsView.java
index 3d89403..68cc481 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/LauncherRecentsView.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/LauncherRecentsView.java
@@ -157,9 +157,8 @@
if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
if (tv.isRunningTask()) {
mTransformParams.setProgress(1 - progress)
- .setCurrentRect(null)
.setSyncTransactionApplier(mSyncTransactionApplier);
- mAppWindowAnimationHelper.applyTransform(mTransformParams);
+ // TODO: Revisit live tiles
} else {
redrawLiveTile(true);
}
@@ -191,18 +190,10 @@
}
@Override
- public void redrawLiveTile(boolean mightNeedToRefill) {
- TransformParams transformParams = getLiveTileParams(mightNeedToRefill);
- if (transformParams != null) {
- mAppWindowAnimationHelper.applyTransform(transformParams);
- }
- }
-
- @Override
public TransformParams getLiveTileParams(
boolean mightNeedToRefill) {
if (!mEnableDrawingLiveTile || mRecentsAnimationController == null
- || mRecentsAnimationTargets == null || mAppWindowAnimationHelper == null) {
+ || mRecentsAnimationTargets == null) {
return null;
}
TaskView taskView = getRunningTaskView();
@@ -222,9 +213,7 @@
if (mightNeedToRefill && offsetY > 0) {
mTempRect.top -= offsetY;
}
- mTempRectF.set(mTempRect);
mTransformParams.setProgress(1f)
- .setCurrentRect(mTempRectF)
.setTargetAlpha(taskView.getAlpha())
.setSyncTransactionApplier(mSyncTransactionApplier)
.setTargetSet(mRecentsAnimationTargets);
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java
index 3273e85..2097b1d 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java
@@ -63,7 +63,6 @@
import android.graphics.Point;
import android.graphics.PointF;
import android.graphics.Rect;
-import android.graphics.RectF;
import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
import android.os.Build;
@@ -126,7 +125,6 @@
import com.android.quickstep.TaskThumbnailCache;
import com.android.quickstep.TaskUtils;
import com.android.quickstep.ViewUtils;
-import com.android.quickstep.util.AppWindowAnimationHelper;
import com.android.quickstep.util.LayoutUtils;
import com.android.quickstep.util.RecentsOrientedState;
import com.android.quickstep.util.SplitScreenBounds;
@@ -214,15 +212,12 @@
protected final BaseActivityInterface mSizeStrategy;
protected RecentsAnimationController mRecentsAnimationController;
protected RecentsAnimationTargets mRecentsAnimationTargets;
- protected AppWindowAnimationHelper mAppWindowAnimationHelper;
protected SyncRtSurfaceTransactionApplierCompat mSyncTransactionApplier;
protected int mTaskWidth;
protected int mTaskHeight;
protected boolean mEnableDrawingLiveTile = false;
protected final Rect mTempRect = new Rect();
- protected final RectF mTempRectF = new RectF();
private final PointF mTempPointF = new PointF();
- private final float[] mTempFloatPoint = new float[2];
private static final int DISMISS_TASK_DURATION = 300;
private static final int ADDITION_TASK_DURATION = 200;
@@ -980,7 +975,6 @@
mRecentsAnimationController = null;
mRecentsAnimationTargets = null;
- mAppWindowAnimationHelper = null;
unloadVisibleTaskData();
setCurrentPage(0);
@@ -2009,11 +2003,6 @@
mRecentsAnimationTargets = recentsAnimationTargets;
}
- // TODO: To be removed in a follow up CL
- public void setAppWindowAnimationHelper(AppWindowAnimationHelper appWindowAnimationHelper) {
- mAppWindowAnimationHelper = appWindowAnimationHelper;
- }
-
public void setLiveTileOverlayAttached(boolean liveTileOverlayAttached) {
mLiveTileOverlayAttached = liveTileOverlayAttached;
}
@@ -2096,13 +2085,20 @@
/**
- * @return How many pixels the running task is offset on the x-axis due to the current scrollX.
+ * @return How many pixels the running task is offset on the currently laid out dominant axis.
*/
public int getScrollOffset() {
- if (getRunningTaskIndex() == -1) {
+ return getScrollOffset(getRunningTaskIndex());
+ }
+
+ /**
+ * @return How many pixels the page is offset on the currently laid out dominant axis.
+ */
+ public int getScrollOffset(int pageIndex) {
+ if (pageIndex == -1) {
return 0;
}
- return getScrollForPage(getRunningTaskIndex()) - mOrientationHandler.getPrimaryScroll(this);
+ return getScrollForPage(pageIndex) - mOrientationHandler.getPrimaryScroll(this);
}
public Consumer<MotionEvent> getEventDispatcher(float navbarRotation) {
@@ -2134,10 +2130,6 @@
};
}
- public AppWindowAnimationHelper getClipAnimationHelper() {
- return mAppWindowAnimationHelper;
- }
-
public TransformParams getLiveTileParams(
boolean mightNeedToRefill) {
return null;