Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a608d813 authored by [1;3C's avatar [1;3C Committed by Evan Rosky
Browse files

Add rotation support to launch animations

This only adds support for launch animations. Recents
requires some auxiliar work.

Adds a rotation parameter to the animation targets that
only gets used by shell transitions. If this is non-zero,
launcher will transform it's coordinates relative to that
provide rotation.

Bug: 179308296
Test: Launch and exit apps with different orientation from
      default (portrait).
Change-Id: I7b52cbd37432bcd43e7155bcb07b30cc65c43186
parent 1e024358
Loading
Loading
Loading
Loading
+83 −28
Original line number Original line Diff line number Diff line
@@ -314,9 +314,11 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
        // before our internal listeners.
        // before our internal listeners.
        mLauncher.getStateManager().setCurrentAnimation(anim);
        mLauncher.getStateManager().setCurrentAnimation(anim);


        Rect windowTargetBounds = getWindowTargetBounds(appTargets);
        final int rotationChange = getRotationChange(appTargets);
        // Note: the targetBounds are relative to the launcher
        Rect windowTargetBounds = getWindowTargetBounds(appTargets, rotationChange);
        anim.play(getOpeningWindowAnimators(v, appTargets, wallpaperTargets, windowTargetBounds,
        anim.play(getOpeningWindowAnimators(v, appTargets, wallpaperTargets, windowTargetBounds,
                areAllTargetsTranslucent(appTargets)));
                areAllTargetsTranslucent(appTargets), rotationChange));
        if (launcherClosing) {
        if (launcherClosing) {
            Pair<AnimatorSet, Runnable> launcherContentAnimator =
            Pair<AnimatorSet, Runnable> launcherContentAnimator =
                    getLauncherContentAnimator(true /* isAppOpening */,
                    getLauncherContentAnimator(true /* isAppOpening */,
@@ -345,19 +347,29 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
     * In multiwindow mode, we need to get the final size of the opening app window target to help
     * In multiwindow mode, we need to get the final size of the opening app window target to help
     * figure out where the floating view should animate to.
     * figure out where the floating view should animate to.
     */
     */
    private Rect getWindowTargetBounds(RemoteAnimationTargetCompat[] appTargets) {
    private Rect getWindowTargetBounds(@NonNull RemoteAnimationTargetCompat[] appTargets,
        Rect bounds = new Rect(0, 0, mDeviceProfile.widthPx, mDeviceProfile.heightPx);
            int rotationChange) {
        if (mLauncher.isInMultiWindowMode()) {
        RemoteAnimationTargetCompat target = null;
            for (RemoteAnimationTargetCompat target : appTargets) {
        for (RemoteAnimationTargetCompat t : appTargets) {
                if (target.mode == MODE_OPENING) {
            if (t.mode != MODE_OPENING) continue;
                    bounds.set(target.screenSpaceBounds);
            target = t;
            break;
        }
        if (target == null) return new Rect(0, 0, mDeviceProfile.widthPx, mDeviceProfile.heightPx);
        final Rect bounds = new Rect(target.screenSpaceBounds);
        if (target.localBounds != null) {
        if (target.localBounds != null) {
            bounds.set(target.localBounds);
            bounds.set(target.localBounds);
        } else {
        } else {
            bounds.offsetTo(target.position.x, target.position.y);
            bounds.offsetTo(target.position.x, target.position.y);
        }
        }
                    return bounds;
        if (rotationChange != 0) {
                }
            if ((rotationChange % 2) == 1) {
                // undoing rotation, so our "original" parent size is actually flipped
                Utilities.rotateBounds(bounds, mDeviceProfile.heightPx, mDeviceProfile.widthPx,
                        4 - rotationChange);
            } else {
                Utilities.rotateBounds(bounds, mDeviceProfile.widthPx, mDeviceProfile.heightPx,
                        4 - rotationChange);
            }
            }
        }
        }
        return bounds;
        return bounds;
@@ -510,7 +522,7 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
    private Animator getOpeningWindowAnimators(View v,
    private Animator getOpeningWindowAnimators(View v,
            RemoteAnimationTargetCompat[] appTargets,
            RemoteAnimationTargetCompat[] appTargets,
            RemoteAnimationTargetCompat[] wallpaperTargets,
            RemoteAnimationTargetCompat[] wallpaperTargets,
            Rect windowTargetBounds, boolean appTargetsAreTranslucent) {
            Rect windowTargetBounds, boolean appTargetsAreTranslucent, int rotationChange) {
        RectF launcherIconBounds = new RectF();
        RectF launcherIconBounds = new RectF();
        FloatingIconView floatingView = FloatingIconView.getFloatingIconView(mLauncher, v,
        FloatingIconView floatingView = FloatingIconView.getFloatingIconView(mLauncher, v,
                !appTargetsAreTranslucent, launcherIconBounds, true /* isOpening */);
                !appTargetsAreTranslucent, launcherIconBounds, true /* isOpening */);
@@ -610,6 +622,10 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener


                final int windowCropWidth = crop.width();
                final int windowCropWidth = crop.width();
                final int windowCropHeight = crop.height();
                final int windowCropHeight = crop.height();
                if (rotationChange != 0) {
                    Utilities.rotateBounds(crop, mDeviceProfile.widthPx,
                            mDeviceProfile.heightPx, rotationChange);
                }


                // Scale the size of the icon to match the size of the window crop.
                // Scale the size of the icon to match the size of the window crop.
                float scaleX = iconWidth / windowCropWidth;
                float scaleX = iconWidth / windowCropWidth;
@@ -649,7 +665,20 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener


                    if (target.mode == MODE_OPENING) {
                    if (target.mode == MODE_OPENING) {
                        matrix.setScale(scale, scale);
                        matrix.setScale(scale, scale);
                        if (rotationChange == 1) {
                            matrix.postTranslate(windowTransY0,
                                    mDeviceProfile.widthPx - (windowTransX0 + scaledCropWidth));
                        } else if (rotationChange == 2) {
                            matrix.postTranslate(
                                    mDeviceProfile.widthPx - (windowTransX0 + scaledCropWidth),
                                    mDeviceProfile.heightPx - (windowTransY0 + scaledCropHeight));
                        } else if (rotationChange == 3) {
                            matrix.postTranslate(
                                    mDeviceProfile.heightPx - (windowTransY0 + scaledCropHeight),
                                    windowTransX0);
                        } else {
                            matrix.postTranslate(windowTransX0, windowTransY0);
                            matrix.postTranslate(windowTransX0, windowTransY0);
                        }


                        floatingView.update(floatingIconBounds, mIconAlpha.value, percent, 0f,
                        floatingView.update(floatingIconBounds, mIconAlpha.value, percent, 0f,
                                mWindowRadius.value * scale, true /* isOpening */);
                                mWindowRadius.value * scale, true /* isOpening */);
@@ -658,17 +687,25 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
                                .withAlpha(1f - mIconAlpha.value)
                                .withAlpha(1f - mIconAlpha.value)
                                .withCornerRadius(mWindowRadius.value)
                                .withCornerRadius(mWindowRadius.value)
                                .withShadowRadius(mShadowRadius.value);
                                .withShadowRadius(mShadowRadius.value);
                    } else {
                    } else if (target.mode == MODE_CLOSING) {
                        if (target.localBounds != null) {
                        if (target.localBounds != null) {
                            final Rect localBounds = target.localBounds;
                            final Rect localBounds = target.localBounds;
                            tmpPos.set(target.localBounds.left, target.localBounds.top);
                            tmpPos.set(target.localBounds.left, target.localBounds.top);
                        } else {
                        } else {
                            tmpPos.set(target.position.x, target.position.y);
                            tmpPos.set(target.position.x, target.position.y);
                        }
                        }

                        matrix.setTranslate(tmpPos.x, tmpPos.y);
                        final Rect crop = new Rect(target.screenSpaceBounds);
                        final Rect crop = new Rect(target.screenSpaceBounds);
                        crop.offsetTo(0, 0);
                        crop.offsetTo(0, 0);

                        if ((rotationChange % 2) == 1) {
                            int tmp = crop.right;
                            crop.right = crop.bottom;
                            crop.bottom = tmp;
                            tmp = tmpPos.x;
                            tmpPos.x = tmpPos.y;
                            tmpPos.y = tmp;
                        }
                        matrix.setTranslate(tmpPos.x, tmpPos.y);
                        builder.withMatrix(matrix)
                        builder.withMatrix(matrix)
                                .withWindowCrop(crop)
                                .withWindowCrop(crop)
                                .withAlpha(1f);
                                .withAlpha(1f);
@@ -825,14 +862,26 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
        return unlockAnimator;
        return unlockAnimator;
    }
    }


    private static int getRotationChange(RemoteAnimationTargetCompat[] appTargets) {
        int rotationChange = 0;
        for (RemoteAnimationTargetCompat target : appTargets) {
            if (Math.abs(target.rotationChange) > Math.abs(rotationChange)) {
                rotationChange = target.rotationChange;
            }
        }
        return rotationChange;
    }

    /**
    /**
     * Animator that controls the transformations of the windows the targets that are closing.
     * Animator that controls the transformations of the windows the targets that are closing.
     */
     */
    private Animator getClosingWindowAnimators(RemoteAnimationTargetCompat[] appTargets,
    private Animator getClosingWindowAnimators(RemoteAnimationTargetCompat[] appTargets,
            RemoteAnimationTargetCompat[] wallpaperTargets) {
            RemoteAnimationTargetCompat[] wallpaperTargets) {
        final int rotationChange = getRotationChange(appTargets);
        SurfaceTransactionApplier surfaceApplier = new SurfaceTransactionApplier(mDragLayer);
        SurfaceTransactionApplier surfaceApplier = new SurfaceTransactionApplier(mDragLayer);
        Matrix matrix = new Matrix();
        Matrix matrix = new Matrix();
        Point tmpPos = new Point();
        Point tmpPos = new Point();
        Rect tmpRect = new Rect();
        ValueAnimator closingAnimator = ValueAnimator.ofFloat(0, 1);
        ValueAnimator closingAnimator = ValueAnimator.ofFloat(0, 1);
        int duration = CLOSING_TRANSITION_DURATION_MS;
        int duration = CLOSING_TRANSITION_DURATION_MS;
        float windowCornerRadius = mDeviceProfile.isMultiWindowMode
        float windowCornerRadius = mDeviceProfile.isMultiWindowMode
@@ -859,26 +908,32 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
                        tmpPos.set(target.position.x, target.position.y);
                        tmpPos.set(target.position.x, target.position.y);
                    }
                    }


                    final Rect crop = new Rect(target.screenSpaceBounds);
                    crop.offsetTo(0, 0);
                    if (target.mode == MODE_CLOSING) {
                    if (target.mode == MODE_CLOSING) {
                        tmpRect.set(target.screenSpaceBounds);
                        if ((rotationChange % 2) != 0) {
                            final int right = crop.right;
                            crop.right = crop.bottom;
                            crop.bottom = right;
                        }
                        matrix.setScale(mScale.value, mScale.value,
                        matrix.setScale(mScale.value, mScale.value,
                                target.screenSpaceBounds.centerX(),
                                tmpRect.centerX(),
                                target.screenSpaceBounds.centerY());
                                tmpRect.centerY());
                        matrix.postTranslate(0, mDy.value);
                        matrix.postTranslate(0, mDy.value);
                        matrix.postTranslate(tmpPos.x, tmpPos.y);
                        matrix.postTranslate(tmpPos.x, tmpPos.y);
                        builder.withMatrix(matrix)
                        builder.withMatrix(matrix)
                                .withWindowCrop(crop)
                                .withAlpha(mAlpha.value)
                                .withAlpha(mAlpha.value)
                                .withCornerRadius(windowCornerRadius)
                                .withCornerRadius(windowCornerRadius)
                                .withShadowRadius(mShadowRadius.value);
                                .withShadowRadius(mShadowRadius.value);
                    } else {
                    } else if (target.mode == MODE_OPENING) {
                        matrix.setTranslate(tmpPos.x, tmpPos.y);
                        matrix.setTranslate(tmpPos.x, tmpPos.y);
                        builder.withMatrix(matrix)
                        builder.withMatrix(matrix)
                                .withWindowCrop(crop)
                                .withAlpha(1f);
                                .withAlpha(1f);
                    }
                    }
                    final Rect crop = new Rect(target.screenSpaceBounds);
                    params[i] = builder.build();
                    crop.offsetTo(0, 0);
                    params[i] = builder
                            .withWindowCrop(crop)
                            .build();
                }
                }
                surfaceApplier.scheduleApply(params);
                surfaceApplier.scheduleApply(params);
            }
            }
+31 −0
Original line number Original line Diff line number Diff line
@@ -700,6 +700,37 @@ public final class Utilities {
        return (Math.abs(first - second) / Math.abs((first + second) / 2.0f)) > bound;
        return (Math.abs(first - second) / Math.abs((first + second) / 2.0f)) > bound;
    }
    }


    /**
     * Rotates `inOutBounds` by `delta` 90-degree increments. Rotation is visually CCW. Parent
     * sizes represent the "space" that will rotate carrying inOutBounds along with it to determine
     * the final bounds.
     */
    public static void rotateBounds(Rect inOutBounds, int parentWidth, int parentHeight,
            int delta) {
        int rdelta = ((delta % 4) + 4) % 4;
        int origLeft = inOutBounds.left;
        switch (rdelta) {
            case 0:
                return;
            case 1:
                inOutBounds.left = inOutBounds.top;
                inOutBounds.top = parentWidth - inOutBounds.right;
                inOutBounds.right = inOutBounds.bottom;
                inOutBounds.bottom = parentWidth - origLeft;
                return;
            case 2:
                inOutBounds.left = parentWidth - inOutBounds.right;
                inOutBounds.right = parentWidth - origLeft;
                return;
            case 3:
                inOutBounds.left = parentHeight - inOutBounds.bottom;
                inOutBounds.bottom = inOutBounds.right;
                inOutBounds.right = parentHeight - inOutBounds.top;
                inOutBounds.top = origLeft;
                return;
        }
    }

    private static class FixedSizeEmptyDrawable extends ColorDrawable {
    private static class FixedSizeEmptyDrawable extends ColorDrawable {


        private final int mSize;
        private final int mSize;