Loading quickstep/res/layout/task_grouped.xml 0 → 100644 +47 −0 Original line number Original line Diff line number Diff line <?xml version="1.0" encoding="utf-8"?><!-- Copyright (C) 2021 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. --> <!-- NOTE! don't add dimensions for margins / paddings / sizes that change per orientation to this file, they need to be loaded at runtime. --> <!-- DOUBLE NOTE! Don't deviate IDs from task.xml since this layout acts as a "subclass" (read as "bad code"). How can we use the view pool in RecentsView to use task.xml layout with using GroupedTaskView.java class? Is that possible (while still keeping code in separate class) ? --> <com.android.quickstep.views.GroupedTaskView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:clipChildren="false" android:defaultFocusHighlightEnabled="false" android:focusable="true"> <com.android.quickstep.views.TaskThumbnailView android:id="@+id/snapshot" android:layout_width="match_parent" android:layout_height="match_parent"/> <com.android.quickstep.views.TaskThumbnailView android:id="@+id/bottomright_snapshot" android:layout_width="match_parent" android:layout_height="match_parent"/> <com.android.quickstep.views.IconView android:id="@+id/icon" android:layout_width="@dimen/task_thumbnail_icon_size" android:layout_height="@dimen/task_thumbnail_icon_size" android:focusable="false" android:importantForAccessibility="no"/> </com.android.quickstep.views.GroupedTaskView> No newline at end of file quickstep/robolectric_tests/src/com/android/quickstep/RecentsActivityTest.java +1 −1 Original line number Original line Diff line number Diff line Loading @@ -63,7 +63,7 @@ public class RecentsActivityTest { RunningTaskInfo placeholderTask = new RunningTaskInfo(); RunningTaskInfo placeholderTask = new RunningTaskInfo(); placeholderTask.taskId = 22; placeholderTask.taskId = 22; frv.showCurrentTask(placeholderTask); frv.showCurrentTask(new RunningTaskInfo[]{placeholderTask}); doLayout(activity); doLayout(activity); ThumbnailData thumbnailData = new ThumbnailData(); ThumbnailData thumbnailData = new ThumbnailData(); Loading quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java +103 −54 Original line number Original line Diff line number Diff line Loading @@ -99,6 +99,7 @@ import com.android.quickstep.util.ActivityInitListener; import com.android.quickstep.util.AnimatorControllerWithResistance; import com.android.quickstep.util.AnimatorControllerWithResistance; import com.android.quickstep.util.InputConsumerProxy; import com.android.quickstep.util.InputConsumerProxy; import com.android.quickstep.util.InputProxyHandlerFactory; import com.android.quickstep.util.InputProxyHandlerFactory; import com.android.quickstep.util.LauncherSplitScreenListener; import com.android.quickstep.util.MotionPauseDetector; import com.android.quickstep.util.MotionPauseDetector; import com.android.quickstep.util.ProtoTracer; import com.android.quickstep.util.ProtoTracer; import com.android.quickstep.util.RecentsOrientedState; import com.android.quickstep.util.RecentsOrientedState; Loading @@ -106,6 +107,7 @@ import com.android.quickstep.util.RectFSpringAnim; import com.android.quickstep.util.StaggeredWorkspaceAnim; import com.android.quickstep.util.StaggeredWorkspaceAnim; import com.android.quickstep.util.SurfaceTransactionApplier; import com.android.quickstep.util.SurfaceTransactionApplier; import com.android.quickstep.util.SwipePipToHomeAnimator; import com.android.quickstep.util.SwipePipToHomeAnimator; import com.android.quickstep.util.TaskViewSimulator; import com.android.quickstep.util.TransformParams; import com.android.quickstep.util.TransformParams; import com.android.quickstep.views.RecentsView; import com.android.quickstep.views.RecentsView; import com.android.quickstep.views.TaskView; import com.android.quickstep.views.TaskView; Loading Loading @@ -222,7 +224,7 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>, protected final TaskAnimationManager mTaskAnimationManager; protected final TaskAnimationManager mTaskAnimationManager; // Either RectFSpringAnim (if animating home) or ObjectAnimator (from mCurrentShift) otherwise // Either RectFSpringAnim (if animating home) or ObjectAnimator (from mCurrentShift) otherwise private RunningWindowAnim mRunningWindowAnim; private RunningWindowAnim[] mRunningWindowAnim; // Possible second animation running at the same time as mRunningWindowAnim // Possible second animation running at the same time as mRunningWindowAnim private Animator mParallelRunningAnim; private Animator mParallelRunningAnim; private boolean mIsMotionPaused; private boolean mIsMotionPaused; Loading Loading @@ -253,6 +255,10 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>, private SwipePipToHomeAnimator mSwipePipToHomeAnimator; private SwipePipToHomeAnimator mSwipePipToHomeAnimator; protected boolean mIsSwipingPipToHome; protected boolean mIsSwipingPipToHome; // TODO(b/195473090) no split PIP for now, remove once we have more clarity // can try to have RectFSpringAnim evaluate multiple rects at once private final SwipePipToHomeAnimator[] mSwipePipToHomeAnimators = new SwipePipToHomeAnimator[2]; // Interpolate RecentsView scale from start of quick switch scroll until this scroll threshold // Interpolate RecentsView scale from start of quick switch scroll until this scroll threshold private final float mQuickSwitchScaleScrollThreshold; private final float mQuickSwitchScaleScrollThreshold; Loading Loading @@ -426,7 +432,8 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>, // RecentsView never updates the display rotation until swipe-up, force update // RecentsView never updates the display rotation until swipe-up, force update // RecentsOrientedState before passing to TaskViewSimulator. // RecentsOrientedState before passing to TaskViewSimulator. mRecentsView.updateRecentsRotation(); mRecentsView.updateRecentsRotation(); mTaskViewSimulator.setOrientationState(mRecentsView.getPagedViewOrientedState()); runActionOnRemoteHandles(remoteTargetHandle -> remoteTargetHandle.mTaskViewSimulator .setOrientationState(mRecentsView.getPagedViewOrientedState())); // If we've already ended the gesture and are going home, don't prepare recents UI, // If we've already ended the gesture and are going home, don't prepare recents UI, // as that will set the state as BACKGROUND_APP, overriding the animation to NORMAL. // as that will set the state as BACKGROUND_APP, overriding the animation to NORMAL. Loading Loading @@ -519,7 +526,21 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>, } } protected void notifyGestureAnimationStartToRecents() { protected void notifyGestureAnimationStartToRecents() { mRecentsView.onGestureAnimationStart(mGestureState.getRunningTask()); ActivityManager.RunningTaskInfo[] runningTasks; if (mIsSwipeForStagedSplit) { int[] splitTaskIds = LauncherSplitScreenListener.INSTANCE.getNoCreate().getSplitTaskIds(); runningTasks = new ActivityManager.RunningTaskInfo[splitTaskIds.length]; for (int i = 0; i < splitTaskIds.length; i++) { int taskId = splitTaskIds[i]; ActivityManager.RunningTaskInfo rti = new ActivityManager.RunningTaskInfo(); rti.taskId = taskId; runningTasks[i] = rti; } } else { runningTasks = new ActivityManager.RunningTaskInfo[]{mGestureState.getRunningTask()}; } mRecentsView.onGestureAnimationStart(runningTasks); } } private void launcherFrameDrawn() { private void launcherFrameDrawn() { Loading Loading @@ -606,15 +627,15 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>, if (animate) { if (animate) { ValueAnimator reapplyWindowTransformAnim = ValueAnimator.ofFloat(0, 1); ValueAnimator reapplyWindowTransformAnim = ValueAnimator.ofFloat(0, 1); reapplyWindowTransformAnim.addUpdateListener(anim -> { reapplyWindowTransformAnim.addUpdateListener(anim -> { if (mRunningWindowAnim == null) { if (mRunningWindowAnim == null || mRunningWindowAnim.length == 0) { applyWindowTransform(); applyScrollAndTransform(); } } }); }); reapplyWindowTransformAnim.setDuration(RECENTS_ATTACH_DURATION).start(); reapplyWindowTransformAnim.setDuration(RECENTS_ATTACH_DURATION).start(); mStateCallback.runOnceAtState(STATE_HANDLER_INVALIDATED, mStateCallback.runOnceAtState(STATE_HANDLER_INVALIDATED, reapplyWindowTransformAnim::cancel); reapplyWindowTransformAnim::cancel); } else { } else { applyWindowTransform(); applyScrollAndTransform(); } } } } Loading Loading @@ -678,7 +699,7 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>, } } updateSysUiFlags(mCurrentShift.value); updateSysUiFlags(mCurrentShift.value); applyWindowTransform(); applyScrollAndTransform(); updateLauncherTransitionProgress(); updateLauncherTransitionProgress(); } } Loading Loading @@ -724,24 +745,23 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>, @Override @Override public void onRecentsAnimationStart(RecentsAnimationController controller, public void onRecentsAnimationStart(RecentsAnimationController controller, RecentsAnimationTargets targets) { RecentsAnimationTargets targets) { ActiveGestureLog.INSTANCE.addLog("startRecentsAnimationCallback", targets.apps.length); super.onRecentsAnimationStart(controller, targets); mRecentsAnimationController = controller; mRecentsAnimationController = controller; mRecentsAnimationTargets = targets; mRecentsAnimationTargets = targets; mTransformParams.setTargetSet(mRecentsAnimationTargets); RemoteAnimationTargetCompat runningTaskTarget = targets.findTask( mGestureState.getRunningTaskId()); if (runningTaskTarget != null) { mTaskViewSimulator.setPreview(runningTaskTarget); } // Only initialize the device profile, if it has not been initialized before, as in some // Only initialize the device profile, if it has not been initialized before, as in some // configurations targets.homeContentInsets may not be correct. // configurations targets.homeContentInsets may not be correct. if (mActivity == null) { if (mActivity == null) { DeviceProfile dp = mTaskViewSimulator.getOrientationState().getLauncherDeviceProfile(); RemoteAnimationTargetCompat primaryTaskTarget = targets.apps[0]; if (targets.minimizedHomeBounds != null && runningTaskTarget != null) { // orientation state is independent of which remote target handle we use since both // should be pointing to the same one. Just choose index 0 for now since that works for // both split and non-split RecentsOrientedState orientationState = mRemoteTargetHandles[0].mTaskViewSimulator .getOrientationState(); DeviceProfile dp = orientationState.getLauncherDeviceProfile(); if (targets.minimizedHomeBounds != null && primaryTaskTarget != null) { Rect overviewStackBounds = mActivityInterface Rect overviewStackBounds = mActivityInterface .getOverviewWindowBounds(targets.minimizedHomeBounds, runningTaskTarget); .getOverviewWindowBounds(targets.minimizedHomeBounds, primaryTaskTarget); dp = dp.getMultiWindowProfile(mContext, dp = dp.getMultiWindowProfile(mContext, new WindowBounds(overviewStackBounds, targets.homeContentInsets)); new WindowBounds(overviewStackBounds, targets.homeContentInsets)); } else { } else { Loading @@ -751,7 +771,7 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>, dp.updateInsets(targets.homeContentInsets); dp.updateInsets(targets.homeContentInsets); dp.updateIsSeascape(mContext); dp.updateIsSeascape(mContext); initTransitionEndpoints(dp); initTransitionEndpoints(dp); mTaskViewSimulator.getOrientationState().setMultiWindowMode(dp.isMultiWindowMode); orientationState.setMultiWindowMode(dp.isMultiWindowMode); } } // Notify when the animation starts // Notify when the animation starts Loading Loading @@ -869,9 +889,17 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>, private void endRunningWindowAnim(boolean cancel) { private void endRunningWindowAnim(boolean cancel) { if (mRunningWindowAnim != null) { if (mRunningWindowAnim != null) { if (cancel) { if (cancel) { mRunningWindowAnim.cancel(); for (RunningWindowAnim r : mRunningWindowAnim) { if (r != null) { r.cancel(); } } } else { } else { mRunningWindowAnim.end(); for (RunningWindowAnim r : mRunningWindowAnim) { if (r != null) { r.end(); } } } } } } if (mParallelRunningAnim != null) { if (mParallelRunningAnim != null) { Loading Loading @@ -1181,15 +1209,17 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>, createHomeAnimationFactory(cookies, duration, isTranslucent, appCanEnterPip, createHomeAnimationFactory(cookies, duration, isTranslucent, appCanEnterPip, runningTaskTarget); runningTaskTarget); mIsSwipingPipToHome = homeAnimFactory.supportSwipePipToHome() && appCanEnterPip; mIsSwipingPipToHome = homeAnimFactory.supportSwipePipToHome() && appCanEnterPip; final RectFSpringAnim windowAnim; final RectFSpringAnim[] windowAnim; if (mIsSwipingPipToHome) { if (mIsSwipingPipToHome) { mSwipePipToHomeAnimator = createWindowAnimationToPip( mSwipePipToHomeAnimator = createWindowAnimationToPip( homeAnimFactory, runningTaskTarget, start); homeAnimFactory, runningTaskTarget, start); windowAnim = mSwipePipToHomeAnimator; mSwipePipToHomeAnimators[0] = mSwipePipToHomeAnimator; windowAnim = mSwipePipToHomeAnimators; } else { } else { mSwipePipToHomeAnimator = null; mSwipePipToHomeAnimator = null; windowAnim = createWindowAnimationToHome(start, homeAnimFactory); windowAnim = createWindowAnimationToHome(start, homeAnimFactory); windowAnim.addAnimatorListener(new AnimationSuccessListener() { windowAnim[0].addAnimatorListener(new AnimationSuccessListener() { @Override @Override public void onAnimationSuccess(Animator animator) { public void onAnimationSuccess(Animator animator) { if (mRecentsAnimationController == null) { if (mRecentsAnimationController == null) { Loading @@ -1203,15 +1233,22 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>, } } }); }); } } windowAnim.start(mContext, velocityPxPerMs); mRunningWindowAnim = new RunningWindowAnim[windowAnim.length]; mRunningWindowAnim = RunningWindowAnim.wrap(windowAnim); for (int i = 0, windowAnimLength = windowAnim.length; i < windowAnimLength; i++) { RectFSpringAnim windowAnimation = windowAnim[i]; if (windowAnimation == null) { continue; } windowAnimation.start(mContext, velocityPxPerMs); mRunningWindowAnim[i] = RunningWindowAnim.wrap(windowAnimation); } homeAnimFactory.setSwipeVelocity(velocityPxPerMs.y); homeAnimFactory.setSwipeVelocity(velocityPxPerMs.y); homeAnimFactory.playAtomicAnimation(velocityPxPerMs.y); homeAnimFactory.playAtomicAnimation(velocityPxPerMs.y); mLauncherTransitionController = null; mLauncherTransitionController = null; if (mRecentsView != null) { if (mRecentsView != null) { mRecentsView.onPrepareGestureEndAnimation(null, mGestureState.getEndTarget(), mRecentsView.onPrepareGestureEndAnimation(null, mGestureState.getEndTarget(), mTaskViewSimulator); getRemoteTaskViewSimulators()); } } } else { } else { AnimatorSet animatorSet = new AnimatorSet(); AnimatorSet animatorSet = new AnimatorSet(); Loading Loading @@ -1253,11 +1290,12 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>, animatorSet.play(windowAnim); animatorSet.play(windowAnim); if (mRecentsView != null) { if (mRecentsView != null) { mRecentsView.onPrepareGestureEndAnimation( mRecentsView.onPrepareGestureEndAnimation( animatorSet, mGestureState.getEndTarget(), mTaskViewSimulator); animatorSet, mGestureState.getEndTarget(), getRemoteTaskViewSimulators()); } } animatorSet.setDuration(duration).setInterpolator(interpolator); animatorSet.setDuration(duration).setInterpolator(interpolator); animatorSet.start(); animatorSet.start(); mRunningWindowAnim = RunningWindowAnim.wrap(animatorSet); mRunningWindowAnim = new RunningWindowAnim[]{RunningWindowAnim.wrap(animatorSet)}; } } } } Loading @@ -1272,16 +1310,21 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>, } } } } /** * TODO(b/195473090) handle multiple task simulators (if needed) for PIP */ private SwipePipToHomeAnimator createWindowAnimationToPip(HomeAnimationFactory homeAnimFactory, private SwipePipToHomeAnimator createWindowAnimationToPip(HomeAnimationFactory homeAnimFactory, RemoteAnimationTargetCompat runningTaskTarget, float startProgress) { RemoteAnimationTargetCompat runningTaskTarget, float startProgress) { // Directly animate the app to PiP (picture-in-picture) mode // Directly animate the app to PiP (picture-in-picture) mode final ActivityManager.RunningTaskInfo taskInfo = mGestureState.getRunningTask(); final ActivityManager.RunningTaskInfo taskInfo = mGestureState.getRunningTask(); final RecentsOrientedState orientationState = mTaskViewSimulator.getOrientationState(); final RecentsOrientedState orientationState = mRemoteTargetHandles[0].mTaskViewSimulator .getOrientationState(); final int windowRotation = calculateWindowRotation(runningTaskTarget, orientationState); final int windowRotation = calculateWindowRotation(runningTaskTarget, orientationState); final int homeRotation = orientationState.getRecentsActivityRotation(); final int homeRotation = orientationState.getRecentsActivityRotation(); final Matrix homeToWindowPositionMap = new Matrix(); final Matrix homeToWindowPositionMap = new Matrix(); final RectF startRect = updateProgressForStartRect(homeToWindowPositionMap, startProgress); final RectF startRect = updateProgressForStartRect(homeToWindowPositionMap, startProgress)[0]; // Move the startRect to Launcher space as floatingIconView runs in Launcher // Move the startRect to Launcher space as floatingIconView runs in Launcher final Matrix windowToHomePositionMap = new Matrix(); final Matrix windowToHomePositionMap = new Matrix(); homeToWindowPositionMap.invert(windowToHomePositionMap); homeToWindowPositionMap.invert(windowToHomePositionMap); Loading Loading @@ -1310,7 +1353,7 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>, // is not ROTATION_0 (which implies the rotation is turned on in launcher settings). // is not ROTATION_0 (which implies the rotation is turned on in launcher settings). if (homeRotation == ROTATION_0 if (homeRotation == ROTATION_0 && (windowRotation == ROTATION_90 || windowRotation == ROTATION_270)) { && (windowRotation == ROTATION_90 || windowRotation == ROTATION_270)) { builder.setFromRotation(mTaskViewSimulator, windowRotation, builder.setFromRotation(mRemoteTargetHandles[0].mTaskViewSimulator, windowRotation, taskInfo.displayCutoutInsets); taskInfo.displayCutoutInsets); } } final SwipePipToHomeAnimator swipePipToHomeAnimator = builder.build(); final SwipePipToHomeAnimator swipePipToHomeAnimator = builder.build(); Loading Loading @@ -1340,7 +1383,7 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>, mGestureState.setState(STATE_END_TARGET_ANIMATION_FINISHED); mGestureState.setState(STATE_END_TARGET_ANIMATION_FINISHED); } } }); }); setupWindowAnimation(swipePipToHomeAnimator); setupWindowAnimation(new RectFSpringAnim[]{swipePipToHomeAnimator}); return swipePipToHomeAnimator; return swipePipToHomeAnimator; } } Loading @@ -1367,19 +1410,19 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>, * @param homeAnimationFactory The home animation factory. * @param homeAnimationFactory The home animation factory. */ */ @Override @Override protected RectFSpringAnim createWindowAnimationToHome(float startProgress, protected RectFSpringAnim[] createWindowAnimationToHome(float startProgress, HomeAnimationFactory homeAnimationFactory) { HomeAnimationFactory homeAnimationFactory) { RectFSpringAnim anim = RectFSpringAnim[] anim = super.createWindowAnimationToHome(startProgress, homeAnimationFactory); super.createWindowAnimationToHome(startProgress, homeAnimationFactory); setupWindowAnimation(anim); setupWindowAnimation(anim); return anim; return anim; } } private void setupWindowAnimation(RectFSpringAnim anim) { private void setupWindowAnimation(RectFSpringAnim[] anims) { anim.addOnUpdateListener((v, r, p) -> { anims[0].addOnUpdateListener((v, r, p) -> { updateSysUiFlags(Math.max(p, mCurrentShift.value)); updateSysUiFlags(Math.max(p, mCurrentShift.value)); }); }); anim.addAnimatorListener(new AnimationSuccessListener() { anims[0].addAnimatorListener(new AnimationSuccessListener() { @Override @Override public void onAnimationSuccess(Animator animator) { public void onAnimationSuccess(Animator animator) { if (mRecentsView != null) { if (mRecentsView != null) { Loading @@ -1391,7 +1434,7 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>, } } }); }); if (mRecentsAnimationTargets != null) { if (mRecentsAnimationTargets != null) { mRecentsAnimationTargets.addReleaseCheck(anim); mRecentsAnimationTargets.addReleaseCheck(anims[0]); } } } } Loading Loading @@ -1639,7 +1682,7 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>, * if applicable. This should happen before {@link #finishRecentsControllerToHome(Runnable)}. * if applicable. This should happen before {@link #finishRecentsControllerToHome(Runnable)}. */ */ private void maybeFinishSwipePipToHome() { private void maybeFinishSwipePipToHome() { if (mIsSwipingPipToHome && mSwipePipToHomeAnimator != null) { if (mIsSwipingPipToHome && mSwipePipToHomeAnimators[0] != null) { SystemUiProxy.INSTANCE.get(mContext).stopSwipePipToHome( SystemUiProxy.INSTANCE.get(mContext).stopSwipePipToHome( mSwipePipToHomeAnimator.getComponentName(), mSwipePipToHomeAnimator.getComponentName(), mSwipePipToHomeAnimator.getDestinationBounds(), mSwipePipToHomeAnimator.getDestinationBounds(), Loading Loading @@ -1680,8 +1723,8 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>, * depend on proper class initialization. * depend on proper class initialization. */ */ protected void initAfterSubclassConstructor() { protected void initAfterSubclassConstructor() { initTransitionEndpoints( initTransitionEndpoints(mRemoteTargetHandles[0].mTaskViewSimulator mTaskViewSimulator.getOrientationState().getLauncherDeviceProfile()); .getOrientationState().getLauncherDeviceProfile()); } } protected void performHapticFeedback() { protected void performHapticFeedback() { Loading @@ -1698,7 +1741,8 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>, protected void linkRecentsViewScroll() { protected void linkRecentsViewScroll() { SurfaceTransactionApplier.create(mRecentsView, applier -> { SurfaceTransactionApplier.create(mRecentsView, applier -> { mTransformParams.setSyncTransactionApplier(applier); runActionOnRemoteHandles(remoteTargetHandle -> remoteTargetHandle.mTransformParams .setSyncTransactionApplier(applier)); runOnRecentsAnimationStart(() -> runOnRecentsAnimationStart(() -> mRecentsAnimationTargets.addReleaseCheck(applier)); mRecentsAnimationTargets.addReleaseCheck(applier)); }); }); Loading Loading @@ -1824,19 +1868,25 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>, /** /** * Applies the transform on the recents animation * Applies the transform on the recents animation */ */ protected void applyWindowTransform() { protected void applyScrollAndTransform() { if (mWindowTransitionController != null) { mWindowTransitionController.setProgress( Math.max(mCurrentShift.value, getScaleProgressDueToScroll()), mDragLengthFactor); } // No need to apply any transform if there is ongoing swipe-pip-to-home animator since // No need to apply any transform if there is ongoing swipe-pip-to-home animator since // that animator handles the leash solely. // that animator handles the leash solely. if (mRecentsAnimationTargets != null && !mIsSwipingPipToHome) { boolean notSwipingPipToHome = mRecentsAnimationTargets != null && !mIsSwipingPipToHome; if (mRecentsViewScrollLinked && mRecentsView != null) { boolean setRecentsScroll = mRecentsViewScrollLinked && mRecentsView != null; mTaskViewSimulator.setScroll(mRecentsView.getScrollOffset()); for (RemoteTargetHandle remoteHandle : mRemoteTargetHandles) { AnimatorControllerWithResistance playbackController = remoteHandle.mPlaybackController; if (playbackController != null) { playbackController.setProgress(Math.max(mCurrentShift.value, getScaleProgressDueToScroll()), mDragLengthFactor); } if (notSwipingPipToHome) { TaskViewSimulator taskViewSimulator = remoteHandle.mTaskViewSimulator; if (setRecentsScroll) { taskViewSimulator.setScroll(mRecentsView.getScrollOffset()); } taskViewSimulator.apply(remoteHandle.mTransformParams); } } mTaskViewSimulator.apply(mTransformParams); } } ProtoTracer.INSTANCE.get(mContext).scheduleFrameUpdate(); ProtoTracer.INSTANCE.get(mContext).scheduleFrameUpdate(); } } Loading Loading @@ -1891,7 +1941,6 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>, } } public interface Factory { public interface Factory { AbsSwipeUpHandler newHandler(GestureState gestureState, long touchTimeMs); AbsSwipeUpHandler newHandler(GestureState gestureState, long touchTimeMs); } } } } quickstep/src/com/android/quickstep/BaseActivityInterface.java +29 −2 Original line number Original line Diff line number Diff line Loading @@ -52,6 +52,7 @@ import com.android.launcher3.statehandlers.DepthController; import com.android.launcher3.statemanager.BaseState; import com.android.launcher3.statemanager.BaseState; import com.android.launcher3.statemanager.StatefulActivity; import com.android.launcher3.statemanager.StatefulActivity; import com.android.launcher3.touch.PagedOrientationHandler; import com.android.launcher3.touch.PagedOrientationHandler; import com.android.launcher3.util.SplitConfigurationOptions; import com.android.launcher3.util.WindowBounds; import com.android.launcher3.util.WindowBounds; import com.android.launcher3.views.ScrimView; import com.android.launcher3.views.ScrimView; import com.android.quickstep.SysUINavigationMode.Mode; import com.android.quickstep.SysUINavigationMode.Mode; Loading Loading @@ -200,11 +201,37 @@ public abstract class BaseActivityInterface<STATE_TYPE extends BaseState<STATE_T recentsView.switchToScreenshot(thumbnailData, runnable); recentsView.switchToScreenshot(thumbnailData, runnable); } } /** * Sets the task size in {@param outRect} taking split screened windows into account. * We assume combined height of both tasks will be same as one normal task, then we'll modify * the task height/width based on the ratio of task screen space bounds from * {@param splitInfo} * * @param desiredStageBounds whether task size for top/left or bottom/right needs to be computed */ public final void calculateStagedSplitTaskSize(Context context, DeviceProfile dp, Rect outRect, SplitConfigurationOptions.StagedSplitBounds splitInfo, @SplitConfigurationOptions.StagePosition int desiredStageBounds) { calculateTaskSize(context, dp, outRect); // TODO(b/181705607) Change for landscape vs portrait float totalHeight = splitInfo.mLeftTopBounds.height() + splitInfo.mRightBottomBounds.height() + splitInfo.mDividerBounds.height() / 2f; float topTaskPercent = splitInfo.mLeftTopBounds.height() / totalHeight; if (desiredStageBounds == SplitConfigurationOptions.STAGE_POSITION_TOP_OR_LEFT) { float diff = outRect.height() * (1f - topTaskPercent); outRect.bottom -= diff; } else { float diff = outRect.height() * topTaskPercent; outRect.top += diff; } } /** /** * Calculates the taskView size for the provided device configuration. * Calculates the taskView size for the provided device configuration. */ */ public final void calculateTaskSize(Context context, DeviceProfile dp, Rect outRect, public final void calculateTaskSize(Context context, DeviceProfile dp, Rect outRect) { PagedOrientationHandler orientedState) { Resources res = context.getResources(); Resources res = context.getResources(); if (dp.overviewShowAsGrid) { if (dp.overviewShowAsGrid) { Rect gridRect = new Rect(); Rect gridRect = new Rect(); Loading quickstep/src/com/android/quickstep/FallbackActivityInterface.java +1 −1 Original line number Original line Diff line number Diff line Loading @@ -57,7 +57,7 @@ public final class FallbackActivityInterface extends @Override @Override public int getSwipeUpDestinationAndLength(DeviceProfile dp, Context context, Rect outRect, public int getSwipeUpDestinationAndLength(DeviceProfile dp, Context context, Rect outRect, PagedOrientationHandler orientationHandler) { PagedOrientationHandler orientationHandler) { calculateTaskSize(context, dp, outRect, orientationHandler); calculateTaskSize(context, dp, outRect); if (dp.isVerticalBarLayout() if (dp.isVerticalBarLayout() && SysUINavigationMode.INSTANCE.get(context).getMode() != NO_BUTTON) { && SysUINavigationMode.INSTANCE.get(context).getMode() != NO_BUTTON) { return dp.isSeascape() ? outRect.left : (dp.widthPx - outRect.right); return dp.isSeascape() ? outRect.left : (dp.widthPx - outRect.right); Loading Loading
quickstep/res/layout/task_grouped.xml 0 → 100644 +47 −0 Original line number Original line Diff line number Diff line <?xml version="1.0" encoding="utf-8"?><!-- Copyright (C) 2021 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. --> <!-- NOTE! don't add dimensions for margins / paddings / sizes that change per orientation to this file, they need to be loaded at runtime. --> <!-- DOUBLE NOTE! Don't deviate IDs from task.xml since this layout acts as a "subclass" (read as "bad code"). How can we use the view pool in RecentsView to use task.xml layout with using GroupedTaskView.java class? Is that possible (while still keeping code in separate class) ? --> <com.android.quickstep.views.GroupedTaskView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:clipChildren="false" android:defaultFocusHighlightEnabled="false" android:focusable="true"> <com.android.quickstep.views.TaskThumbnailView android:id="@+id/snapshot" android:layout_width="match_parent" android:layout_height="match_parent"/> <com.android.quickstep.views.TaskThumbnailView android:id="@+id/bottomright_snapshot" android:layout_width="match_parent" android:layout_height="match_parent"/> <com.android.quickstep.views.IconView android:id="@+id/icon" android:layout_width="@dimen/task_thumbnail_icon_size" android:layout_height="@dimen/task_thumbnail_icon_size" android:focusable="false" android:importantForAccessibility="no"/> </com.android.quickstep.views.GroupedTaskView> No newline at end of file
quickstep/robolectric_tests/src/com/android/quickstep/RecentsActivityTest.java +1 −1 Original line number Original line Diff line number Diff line Loading @@ -63,7 +63,7 @@ public class RecentsActivityTest { RunningTaskInfo placeholderTask = new RunningTaskInfo(); RunningTaskInfo placeholderTask = new RunningTaskInfo(); placeholderTask.taskId = 22; placeholderTask.taskId = 22; frv.showCurrentTask(placeholderTask); frv.showCurrentTask(new RunningTaskInfo[]{placeholderTask}); doLayout(activity); doLayout(activity); ThumbnailData thumbnailData = new ThumbnailData(); ThumbnailData thumbnailData = new ThumbnailData(); Loading
quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java +103 −54 Original line number Original line Diff line number Diff line Loading @@ -99,6 +99,7 @@ import com.android.quickstep.util.ActivityInitListener; import com.android.quickstep.util.AnimatorControllerWithResistance; import com.android.quickstep.util.AnimatorControllerWithResistance; import com.android.quickstep.util.InputConsumerProxy; import com.android.quickstep.util.InputConsumerProxy; import com.android.quickstep.util.InputProxyHandlerFactory; import com.android.quickstep.util.InputProxyHandlerFactory; import com.android.quickstep.util.LauncherSplitScreenListener; import com.android.quickstep.util.MotionPauseDetector; import com.android.quickstep.util.MotionPauseDetector; import com.android.quickstep.util.ProtoTracer; import com.android.quickstep.util.ProtoTracer; import com.android.quickstep.util.RecentsOrientedState; import com.android.quickstep.util.RecentsOrientedState; Loading @@ -106,6 +107,7 @@ import com.android.quickstep.util.RectFSpringAnim; import com.android.quickstep.util.StaggeredWorkspaceAnim; import com.android.quickstep.util.StaggeredWorkspaceAnim; import com.android.quickstep.util.SurfaceTransactionApplier; import com.android.quickstep.util.SurfaceTransactionApplier; import com.android.quickstep.util.SwipePipToHomeAnimator; import com.android.quickstep.util.SwipePipToHomeAnimator; import com.android.quickstep.util.TaskViewSimulator; import com.android.quickstep.util.TransformParams; import com.android.quickstep.util.TransformParams; import com.android.quickstep.views.RecentsView; import com.android.quickstep.views.RecentsView; import com.android.quickstep.views.TaskView; import com.android.quickstep.views.TaskView; Loading Loading @@ -222,7 +224,7 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>, protected final TaskAnimationManager mTaskAnimationManager; protected final TaskAnimationManager mTaskAnimationManager; // Either RectFSpringAnim (if animating home) or ObjectAnimator (from mCurrentShift) otherwise // Either RectFSpringAnim (if animating home) or ObjectAnimator (from mCurrentShift) otherwise private RunningWindowAnim mRunningWindowAnim; private RunningWindowAnim[] mRunningWindowAnim; // Possible second animation running at the same time as mRunningWindowAnim // Possible second animation running at the same time as mRunningWindowAnim private Animator mParallelRunningAnim; private Animator mParallelRunningAnim; private boolean mIsMotionPaused; private boolean mIsMotionPaused; Loading Loading @@ -253,6 +255,10 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>, private SwipePipToHomeAnimator mSwipePipToHomeAnimator; private SwipePipToHomeAnimator mSwipePipToHomeAnimator; protected boolean mIsSwipingPipToHome; protected boolean mIsSwipingPipToHome; // TODO(b/195473090) no split PIP for now, remove once we have more clarity // can try to have RectFSpringAnim evaluate multiple rects at once private final SwipePipToHomeAnimator[] mSwipePipToHomeAnimators = new SwipePipToHomeAnimator[2]; // Interpolate RecentsView scale from start of quick switch scroll until this scroll threshold // Interpolate RecentsView scale from start of quick switch scroll until this scroll threshold private final float mQuickSwitchScaleScrollThreshold; private final float mQuickSwitchScaleScrollThreshold; Loading Loading @@ -426,7 +432,8 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>, // RecentsView never updates the display rotation until swipe-up, force update // RecentsView never updates the display rotation until swipe-up, force update // RecentsOrientedState before passing to TaskViewSimulator. // RecentsOrientedState before passing to TaskViewSimulator. mRecentsView.updateRecentsRotation(); mRecentsView.updateRecentsRotation(); mTaskViewSimulator.setOrientationState(mRecentsView.getPagedViewOrientedState()); runActionOnRemoteHandles(remoteTargetHandle -> remoteTargetHandle.mTaskViewSimulator .setOrientationState(mRecentsView.getPagedViewOrientedState())); // If we've already ended the gesture and are going home, don't prepare recents UI, // If we've already ended the gesture and are going home, don't prepare recents UI, // as that will set the state as BACKGROUND_APP, overriding the animation to NORMAL. // as that will set the state as BACKGROUND_APP, overriding the animation to NORMAL. Loading Loading @@ -519,7 +526,21 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>, } } protected void notifyGestureAnimationStartToRecents() { protected void notifyGestureAnimationStartToRecents() { mRecentsView.onGestureAnimationStart(mGestureState.getRunningTask()); ActivityManager.RunningTaskInfo[] runningTasks; if (mIsSwipeForStagedSplit) { int[] splitTaskIds = LauncherSplitScreenListener.INSTANCE.getNoCreate().getSplitTaskIds(); runningTasks = new ActivityManager.RunningTaskInfo[splitTaskIds.length]; for (int i = 0; i < splitTaskIds.length; i++) { int taskId = splitTaskIds[i]; ActivityManager.RunningTaskInfo rti = new ActivityManager.RunningTaskInfo(); rti.taskId = taskId; runningTasks[i] = rti; } } else { runningTasks = new ActivityManager.RunningTaskInfo[]{mGestureState.getRunningTask()}; } mRecentsView.onGestureAnimationStart(runningTasks); } } private void launcherFrameDrawn() { private void launcherFrameDrawn() { Loading Loading @@ -606,15 +627,15 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>, if (animate) { if (animate) { ValueAnimator reapplyWindowTransformAnim = ValueAnimator.ofFloat(0, 1); ValueAnimator reapplyWindowTransformAnim = ValueAnimator.ofFloat(0, 1); reapplyWindowTransformAnim.addUpdateListener(anim -> { reapplyWindowTransformAnim.addUpdateListener(anim -> { if (mRunningWindowAnim == null) { if (mRunningWindowAnim == null || mRunningWindowAnim.length == 0) { applyWindowTransform(); applyScrollAndTransform(); } } }); }); reapplyWindowTransformAnim.setDuration(RECENTS_ATTACH_DURATION).start(); reapplyWindowTransformAnim.setDuration(RECENTS_ATTACH_DURATION).start(); mStateCallback.runOnceAtState(STATE_HANDLER_INVALIDATED, mStateCallback.runOnceAtState(STATE_HANDLER_INVALIDATED, reapplyWindowTransformAnim::cancel); reapplyWindowTransformAnim::cancel); } else { } else { applyWindowTransform(); applyScrollAndTransform(); } } } } Loading Loading @@ -678,7 +699,7 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>, } } updateSysUiFlags(mCurrentShift.value); updateSysUiFlags(mCurrentShift.value); applyWindowTransform(); applyScrollAndTransform(); updateLauncherTransitionProgress(); updateLauncherTransitionProgress(); } } Loading Loading @@ -724,24 +745,23 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>, @Override @Override public void onRecentsAnimationStart(RecentsAnimationController controller, public void onRecentsAnimationStart(RecentsAnimationController controller, RecentsAnimationTargets targets) { RecentsAnimationTargets targets) { ActiveGestureLog.INSTANCE.addLog("startRecentsAnimationCallback", targets.apps.length); super.onRecentsAnimationStart(controller, targets); mRecentsAnimationController = controller; mRecentsAnimationController = controller; mRecentsAnimationTargets = targets; mRecentsAnimationTargets = targets; mTransformParams.setTargetSet(mRecentsAnimationTargets); RemoteAnimationTargetCompat runningTaskTarget = targets.findTask( mGestureState.getRunningTaskId()); if (runningTaskTarget != null) { mTaskViewSimulator.setPreview(runningTaskTarget); } // Only initialize the device profile, if it has not been initialized before, as in some // Only initialize the device profile, if it has not been initialized before, as in some // configurations targets.homeContentInsets may not be correct. // configurations targets.homeContentInsets may not be correct. if (mActivity == null) { if (mActivity == null) { DeviceProfile dp = mTaskViewSimulator.getOrientationState().getLauncherDeviceProfile(); RemoteAnimationTargetCompat primaryTaskTarget = targets.apps[0]; if (targets.minimizedHomeBounds != null && runningTaskTarget != null) { // orientation state is independent of which remote target handle we use since both // should be pointing to the same one. Just choose index 0 for now since that works for // both split and non-split RecentsOrientedState orientationState = mRemoteTargetHandles[0].mTaskViewSimulator .getOrientationState(); DeviceProfile dp = orientationState.getLauncherDeviceProfile(); if (targets.minimizedHomeBounds != null && primaryTaskTarget != null) { Rect overviewStackBounds = mActivityInterface Rect overviewStackBounds = mActivityInterface .getOverviewWindowBounds(targets.minimizedHomeBounds, runningTaskTarget); .getOverviewWindowBounds(targets.minimizedHomeBounds, primaryTaskTarget); dp = dp.getMultiWindowProfile(mContext, dp = dp.getMultiWindowProfile(mContext, new WindowBounds(overviewStackBounds, targets.homeContentInsets)); new WindowBounds(overviewStackBounds, targets.homeContentInsets)); } else { } else { Loading @@ -751,7 +771,7 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>, dp.updateInsets(targets.homeContentInsets); dp.updateInsets(targets.homeContentInsets); dp.updateIsSeascape(mContext); dp.updateIsSeascape(mContext); initTransitionEndpoints(dp); initTransitionEndpoints(dp); mTaskViewSimulator.getOrientationState().setMultiWindowMode(dp.isMultiWindowMode); orientationState.setMultiWindowMode(dp.isMultiWindowMode); } } // Notify when the animation starts // Notify when the animation starts Loading Loading @@ -869,9 +889,17 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>, private void endRunningWindowAnim(boolean cancel) { private void endRunningWindowAnim(boolean cancel) { if (mRunningWindowAnim != null) { if (mRunningWindowAnim != null) { if (cancel) { if (cancel) { mRunningWindowAnim.cancel(); for (RunningWindowAnim r : mRunningWindowAnim) { if (r != null) { r.cancel(); } } } else { } else { mRunningWindowAnim.end(); for (RunningWindowAnim r : mRunningWindowAnim) { if (r != null) { r.end(); } } } } } } if (mParallelRunningAnim != null) { if (mParallelRunningAnim != null) { Loading Loading @@ -1181,15 +1209,17 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>, createHomeAnimationFactory(cookies, duration, isTranslucent, appCanEnterPip, createHomeAnimationFactory(cookies, duration, isTranslucent, appCanEnterPip, runningTaskTarget); runningTaskTarget); mIsSwipingPipToHome = homeAnimFactory.supportSwipePipToHome() && appCanEnterPip; mIsSwipingPipToHome = homeAnimFactory.supportSwipePipToHome() && appCanEnterPip; final RectFSpringAnim windowAnim; final RectFSpringAnim[] windowAnim; if (mIsSwipingPipToHome) { if (mIsSwipingPipToHome) { mSwipePipToHomeAnimator = createWindowAnimationToPip( mSwipePipToHomeAnimator = createWindowAnimationToPip( homeAnimFactory, runningTaskTarget, start); homeAnimFactory, runningTaskTarget, start); windowAnim = mSwipePipToHomeAnimator; mSwipePipToHomeAnimators[0] = mSwipePipToHomeAnimator; windowAnim = mSwipePipToHomeAnimators; } else { } else { mSwipePipToHomeAnimator = null; mSwipePipToHomeAnimator = null; windowAnim = createWindowAnimationToHome(start, homeAnimFactory); windowAnim = createWindowAnimationToHome(start, homeAnimFactory); windowAnim.addAnimatorListener(new AnimationSuccessListener() { windowAnim[0].addAnimatorListener(new AnimationSuccessListener() { @Override @Override public void onAnimationSuccess(Animator animator) { public void onAnimationSuccess(Animator animator) { if (mRecentsAnimationController == null) { if (mRecentsAnimationController == null) { Loading @@ -1203,15 +1233,22 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>, } } }); }); } } windowAnim.start(mContext, velocityPxPerMs); mRunningWindowAnim = new RunningWindowAnim[windowAnim.length]; mRunningWindowAnim = RunningWindowAnim.wrap(windowAnim); for (int i = 0, windowAnimLength = windowAnim.length; i < windowAnimLength; i++) { RectFSpringAnim windowAnimation = windowAnim[i]; if (windowAnimation == null) { continue; } windowAnimation.start(mContext, velocityPxPerMs); mRunningWindowAnim[i] = RunningWindowAnim.wrap(windowAnimation); } homeAnimFactory.setSwipeVelocity(velocityPxPerMs.y); homeAnimFactory.setSwipeVelocity(velocityPxPerMs.y); homeAnimFactory.playAtomicAnimation(velocityPxPerMs.y); homeAnimFactory.playAtomicAnimation(velocityPxPerMs.y); mLauncherTransitionController = null; mLauncherTransitionController = null; if (mRecentsView != null) { if (mRecentsView != null) { mRecentsView.onPrepareGestureEndAnimation(null, mGestureState.getEndTarget(), mRecentsView.onPrepareGestureEndAnimation(null, mGestureState.getEndTarget(), mTaskViewSimulator); getRemoteTaskViewSimulators()); } } } else { } else { AnimatorSet animatorSet = new AnimatorSet(); AnimatorSet animatorSet = new AnimatorSet(); Loading Loading @@ -1253,11 +1290,12 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>, animatorSet.play(windowAnim); animatorSet.play(windowAnim); if (mRecentsView != null) { if (mRecentsView != null) { mRecentsView.onPrepareGestureEndAnimation( mRecentsView.onPrepareGestureEndAnimation( animatorSet, mGestureState.getEndTarget(), mTaskViewSimulator); animatorSet, mGestureState.getEndTarget(), getRemoteTaskViewSimulators()); } } animatorSet.setDuration(duration).setInterpolator(interpolator); animatorSet.setDuration(duration).setInterpolator(interpolator); animatorSet.start(); animatorSet.start(); mRunningWindowAnim = RunningWindowAnim.wrap(animatorSet); mRunningWindowAnim = new RunningWindowAnim[]{RunningWindowAnim.wrap(animatorSet)}; } } } } Loading @@ -1272,16 +1310,21 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>, } } } } /** * TODO(b/195473090) handle multiple task simulators (if needed) for PIP */ private SwipePipToHomeAnimator createWindowAnimationToPip(HomeAnimationFactory homeAnimFactory, private SwipePipToHomeAnimator createWindowAnimationToPip(HomeAnimationFactory homeAnimFactory, RemoteAnimationTargetCompat runningTaskTarget, float startProgress) { RemoteAnimationTargetCompat runningTaskTarget, float startProgress) { // Directly animate the app to PiP (picture-in-picture) mode // Directly animate the app to PiP (picture-in-picture) mode final ActivityManager.RunningTaskInfo taskInfo = mGestureState.getRunningTask(); final ActivityManager.RunningTaskInfo taskInfo = mGestureState.getRunningTask(); final RecentsOrientedState orientationState = mTaskViewSimulator.getOrientationState(); final RecentsOrientedState orientationState = mRemoteTargetHandles[0].mTaskViewSimulator .getOrientationState(); final int windowRotation = calculateWindowRotation(runningTaskTarget, orientationState); final int windowRotation = calculateWindowRotation(runningTaskTarget, orientationState); final int homeRotation = orientationState.getRecentsActivityRotation(); final int homeRotation = orientationState.getRecentsActivityRotation(); final Matrix homeToWindowPositionMap = new Matrix(); final Matrix homeToWindowPositionMap = new Matrix(); final RectF startRect = updateProgressForStartRect(homeToWindowPositionMap, startProgress); final RectF startRect = updateProgressForStartRect(homeToWindowPositionMap, startProgress)[0]; // Move the startRect to Launcher space as floatingIconView runs in Launcher // Move the startRect to Launcher space as floatingIconView runs in Launcher final Matrix windowToHomePositionMap = new Matrix(); final Matrix windowToHomePositionMap = new Matrix(); homeToWindowPositionMap.invert(windowToHomePositionMap); homeToWindowPositionMap.invert(windowToHomePositionMap); Loading Loading @@ -1310,7 +1353,7 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>, // is not ROTATION_0 (which implies the rotation is turned on in launcher settings). // is not ROTATION_0 (which implies the rotation is turned on in launcher settings). if (homeRotation == ROTATION_0 if (homeRotation == ROTATION_0 && (windowRotation == ROTATION_90 || windowRotation == ROTATION_270)) { && (windowRotation == ROTATION_90 || windowRotation == ROTATION_270)) { builder.setFromRotation(mTaskViewSimulator, windowRotation, builder.setFromRotation(mRemoteTargetHandles[0].mTaskViewSimulator, windowRotation, taskInfo.displayCutoutInsets); taskInfo.displayCutoutInsets); } } final SwipePipToHomeAnimator swipePipToHomeAnimator = builder.build(); final SwipePipToHomeAnimator swipePipToHomeAnimator = builder.build(); Loading Loading @@ -1340,7 +1383,7 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>, mGestureState.setState(STATE_END_TARGET_ANIMATION_FINISHED); mGestureState.setState(STATE_END_TARGET_ANIMATION_FINISHED); } } }); }); setupWindowAnimation(swipePipToHomeAnimator); setupWindowAnimation(new RectFSpringAnim[]{swipePipToHomeAnimator}); return swipePipToHomeAnimator; return swipePipToHomeAnimator; } } Loading @@ -1367,19 +1410,19 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>, * @param homeAnimationFactory The home animation factory. * @param homeAnimationFactory The home animation factory. */ */ @Override @Override protected RectFSpringAnim createWindowAnimationToHome(float startProgress, protected RectFSpringAnim[] createWindowAnimationToHome(float startProgress, HomeAnimationFactory homeAnimationFactory) { HomeAnimationFactory homeAnimationFactory) { RectFSpringAnim anim = RectFSpringAnim[] anim = super.createWindowAnimationToHome(startProgress, homeAnimationFactory); super.createWindowAnimationToHome(startProgress, homeAnimationFactory); setupWindowAnimation(anim); setupWindowAnimation(anim); return anim; return anim; } } private void setupWindowAnimation(RectFSpringAnim anim) { private void setupWindowAnimation(RectFSpringAnim[] anims) { anim.addOnUpdateListener((v, r, p) -> { anims[0].addOnUpdateListener((v, r, p) -> { updateSysUiFlags(Math.max(p, mCurrentShift.value)); updateSysUiFlags(Math.max(p, mCurrentShift.value)); }); }); anim.addAnimatorListener(new AnimationSuccessListener() { anims[0].addAnimatorListener(new AnimationSuccessListener() { @Override @Override public void onAnimationSuccess(Animator animator) { public void onAnimationSuccess(Animator animator) { if (mRecentsView != null) { if (mRecentsView != null) { Loading @@ -1391,7 +1434,7 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>, } } }); }); if (mRecentsAnimationTargets != null) { if (mRecentsAnimationTargets != null) { mRecentsAnimationTargets.addReleaseCheck(anim); mRecentsAnimationTargets.addReleaseCheck(anims[0]); } } } } Loading Loading @@ -1639,7 +1682,7 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>, * if applicable. This should happen before {@link #finishRecentsControllerToHome(Runnable)}. * if applicable. This should happen before {@link #finishRecentsControllerToHome(Runnable)}. */ */ private void maybeFinishSwipePipToHome() { private void maybeFinishSwipePipToHome() { if (mIsSwipingPipToHome && mSwipePipToHomeAnimator != null) { if (mIsSwipingPipToHome && mSwipePipToHomeAnimators[0] != null) { SystemUiProxy.INSTANCE.get(mContext).stopSwipePipToHome( SystemUiProxy.INSTANCE.get(mContext).stopSwipePipToHome( mSwipePipToHomeAnimator.getComponentName(), mSwipePipToHomeAnimator.getComponentName(), mSwipePipToHomeAnimator.getDestinationBounds(), mSwipePipToHomeAnimator.getDestinationBounds(), Loading Loading @@ -1680,8 +1723,8 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>, * depend on proper class initialization. * depend on proper class initialization. */ */ protected void initAfterSubclassConstructor() { protected void initAfterSubclassConstructor() { initTransitionEndpoints( initTransitionEndpoints(mRemoteTargetHandles[0].mTaskViewSimulator mTaskViewSimulator.getOrientationState().getLauncherDeviceProfile()); .getOrientationState().getLauncherDeviceProfile()); } } protected void performHapticFeedback() { protected void performHapticFeedback() { Loading @@ -1698,7 +1741,8 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>, protected void linkRecentsViewScroll() { protected void linkRecentsViewScroll() { SurfaceTransactionApplier.create(mRecentsView, applier -> { SurfaceTransactionApplier.create(mRecentsView, applier -> { mTransformParams.setSyncTransactionApplier(applier); runActionOnRemoteHandles(remoteTargetHandle -> remoteTargetHandle.mTransformParams .setSyncTransactionApplier(applier)); runOnRecentsAnimationStart(() -> runOnRecentsAnimationStart(() -> mRecentsAnimationTargets.addReleaseCheck(applier)); mRecentsAnimationTargets.addReleaseCheck(applier)); }); }); Loading Loading @@ -1824,19 +1868,25 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>, /** /** * Applies the transform on the recents animation * Applies the transform on the recents animation */ */ protected void applyWindowTransform() { protected void applyScrollAndTransform() { if (mWindowTransitionController != null) { mWindowTransitionController.setProgress( Math.max(mCurrentShift.value, getScaleProgressDueToScroll()), mDragLengthFactor); } // No need to apply any transform if there is ongoing swipe-pip-to-home animator since // No need to apply any transform if there is ongoing swipe-pip-to-home animator since // that animator handles the leash solely. // that animator handles the leash solely. if (mRecentsAnimationTargets != null && !mIsSwipingPipToHome) { boolean notSwipingPipToHome = mRecentsAnimationTargets != null && !mIsSwipingPipToHome; if (mRecentsViewScrollLinked && mRecentsView != null) { boolean setRecentsScroll = mRecentsViewScrollLinked && mRecentsView != null; mTaskViewSimulator.setScroll(mRecentsView.getScrollOffset()); for (RemoteTargetHandle remoteHandle : mRemoteTargetHandles) { AnimatorControllerWithResistance playbackController = remoteHandle.mPlaybackController; if (playbackController != null) { playbackController.setProgress(Math.max(mCurrentShift.value, getScaleProgressDueToScroll()), mDragLengthFactor); } if (notSwipingPipToHome) { TaskViewSimulator taskViewSimulator = remoteHandle.mTaskViewSimulator; if (setRecentsScroll) { taskViewSimulator.setScroll(mRecentsView.getScrollOffset()); } taskViewSimulator.apply(remoteHandle.mTransformParams); } } mTaskViewSimulator.apply(mTransformParams); } } ProtoTracer.INSTANCE.get(mContext).scheduleFrameUpdate(); ProtoTracer.INSTANCE.get(mContext).scheduleFrameUpdate(); } } Loading Loading @@ -1891,7 +1941,6 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>, } } public interface Factory { public interface Factory { AbsSwipeUpHandler newHandler(GestureState gestureState, long touchTimeMs); AbsSwipeUpHandler newHandler(GestureState gestureState, long touchTimeMs); } } } }
quickstep/src/com/android/quickstep/BaseActivityInterface.java +29 −2 Original line number Original line Diff line number Diff line Loading @@ -52,6 +52,7 @@ import com.android.launcher3.statehandlers.DepthController; import com.android.launcher3.statemanager.BaseState; import com.android.launcher3.statemanager.BaseState; import com.android.launcher3.statemanager.StatefulActivity; import com.android.launcher3.statemanager.StatefulActivity; import com.android.launcher3.touch.PagedOrientationHandler; import com.android.launcher3.touch.PagedOrientationHandler; import com.android.launcher3.util.SplitConfigurationOptions; import com.android.launcher3.util.WindowBounds; import com.android.launcher3.util.WindowBounds; import com.android.launcher3.views.ScrimView; import com.android.launcher3.views.ScrimView; import com.android.quickstep.SysUINavigationMode.Mode; import com.android.quickstep.SysUINavigationMode.Mode; Loading Loading @@ -200,11 +201,37 @@ public abstract class BaseActivityInterface<STATE_TYPE extends BaseState<STATE_T recentsView.switchToScreenshot(thumbnailData, runnable); recentsView.switchToScreenshot(thumbnailData, runnable); } } /** * Sets the task size in {@param outRect} taking split screened windows into account. * We assume combined height of both tasks will be same as one normal task, then we'll modify * the task height/width based on the ratio of task screen space bounds from * {@param splitInfo} * * @param desiredStageBounds whether task size for top/left or bottom/right needs to be computed */ public final void calculateStagedSplitTaskSize(Context context, DeviceProfile dp, Rect outRect, SplitConfigurationOptions.StagedSplitBounds splitInfo, @SplitConfigurationOptions.StagePosition int desiredStageBounds) { calculateTaskSize(context, dp, outRect); // TODO(b/181705607) Change for landscape vs portrait float totalHeight = splitInfo.mLeftTopBounds.height() + splitInfo.mRightBottomBounds.height() + splitInfo.mDividerBounds.height() / 2f; float topTaskPercent = splitInfo.mLeftTopBounds.height() / totalHeight; if (desiredStageBounds == SplitConfigurationOptions.STAGE_POSITION_TOP_OR_LEFT) { float diff = outRect.height() * (1f - topTaskPercent); outRect.bottom -= diff; } else { float diff = outRect.height() * topTaskPercent; outRect.top += diff; } } /** /** * Calculates the taskView size for the provided device configuration. * Calculates the taskView size for the provided device configuration. */ */ public final void calculateTaskSize(Context context, DeviceProfile dp, Rect outRect, public final void calculateTaskSize(Context context, DeviceProfile dp, Rect outRect) { PagedOrientationHandler orientedState) { Resources res = context.getResources(); Resources res = context.getResources(); if (dp.overviewShowAsGrid) { if (dp.overviewShowAsGrid) { Rect gridRect = new Rect(); Rect gridRect = new Rect(); Loading
quickstep/src/com/android/quickstep/FallbackActivityInterface.java +1 −1 Original line number Original line Diff line number Diff line Loading @@ -57,7 +57,7 @@ public final class FallbackActivityInterface extends @Override @Override public int getSwipeUpDestinationAndLength(DeviceProfile dp, Context context, Rect outRect, public int getSwipeUpDestinationAndLength(DeviceProfile dp, Context context, Rect outRect, PagedOrientationHandler orientationHandler) { PagedOrientationHandler orientationHandler) { calculateTaskSize(context, dp, outRect, orientationHandler); calculateTaskSize(context, dp, outRect); if (dp.isVerticalBarLayout() if (dp.isVerticalBarLayout() && SysUINavigationMode.INSTANCE.get(context).getMode() != NO_BUTTON) { && SysUINavigationMode.INSTANCE.get(context).getMode() != NO_BUTTON) { return dp.isSeascape() ? outRect.left : (dp.widthPx - outRect.right); return dp.isSeascape() ? outRect.left : (dp.widthPx - outRect.right); Loading