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

Commit d7a594d3 authored by Riddle Hsu's avatar Riddle Hsu
Browse files

Use local leash to animate PiP activity surface

Currently shell is not aware of letterbox info of activity.
Especially PiP animation assume the surface is task which
should be put at 0,0 in either task display area or a
multi-window container after expanding.

By using a local leash, the position of activity surface won't
be erased by the end of pip animation, and the animation will
look better by including the area of activity offset.

Bug: 280028520
Test: In a ignore-orientation display or split screen.
      Task[A,B], B requested fixed orientation to trigger letterbox.
      B enter PiP, then then expand to original position.
      The offset from letterbox should not be changed.
Change-Id: I1a24703ce0d9976d0f5dfeda0569226a5afa908c
parent 1c5290f2
Loading
Loading
Loading
Loading
+35 −5
Original line number Diff line number Diff line
@@ -470,6 +470,7 @@ public class PipTransition extends PipTransitionController {
            @NonNull Transitions.TransitionFinishCallback finishCallback,
            @NonNull TaskInfo taskInfo, @Nullable TransitionInfo.Change pipTaskChange) {
        TransitionInfo.Change pipChange = pipTaskChange;
        SurfaceControl activitySc = null;
        if (mCurrentPipTaskToken == null) {
            ProtoLog.w(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
                    "%s: There is no existing PiP Task for TRANSIT_EXIT_PIP", TAG);
@@ -482,6 +483,7 @@ public class PipTransition extends PipTransitionController {
                if (mCurrentPipTaskToken.equals(change.getLastParent())) {
                    // Find the activity that is exiting PiP.
                    pipChange = change;
                    activitySc = change.getLeash();
                    break;
                }
            }
@@ -498,17 +500,36 @@ public class PipTransition extends PipTransitionController {
        // case it may not be in the screen coordinate.
        // Reparent the pip leash to the root with max layer so that we can animate it outside of
        // parent crop, and make sure it is not covered by other windows.
        final SurfaceControl pipLeash = pipChange.getLeash();
        final int rootIdx = TransitionUtil.rootIndexFor(pipChange, info);
        startTransaction.reparent(pipLeash, info.getRoot(rootIdx).getLeash());
        final TransitionInfo.Root root = TransitionUtil.getRootFor(pipChange, info);
        final SurfaceControl pipLeash;
        if (activitySc != null) {
            // Use a local leash to animate activity in case the activity has letterbox which may
            // be broken by PiP animation, e.g. always end at 0,0 in parent and unable to include
            // letterbox area in crop bounds.
            final SurfaceControl activitySurface = pipChange.getLeash();
            pipLeash = new SurfaceControl.Builder()
                    .setName(activitySc + "_pip-leash")
                    .setContainerLayer()
                    .setHidden(false)
                    .setParent(root.getLeash())
                    .build();
            startTransaction.reparent(activitySurface, pipLeash);
            // Put the activity at local position with offset in case it is letterboxed.
            final Point activityOffset = pipChange.getEndRelOffset();
            startTransaction.setPosition(activitySc, activityOffset.x, activityOffset.y);
        } else {
            pipLeash = pipChange.getLeash();
            startTransaction.reparent(pipLeash, root.getLeash());
        }
        startTransaction.setLayer(pipLeash, Integer.MAX_VALUE);
        // Note: because of this, the bounds to animate should be translated to the root coordinate.
        final Point offset = info.getRoot(rootIdx).getOffset();
        final Point offset = root.getOffset();
        final Rect currentBounds = mPipBoundsState.getBounds();
        currentBounds.offset(-offset.x, -offset.y);
        startTransaction.setPosition(pipLeash, currentBounds.left, currentBounds.top);

        final WindowContainerToken pipTaskToken = pipChange.getContainer();
        final boolean useLocalLeash = activitySc != null;
        final boolean toFullscreen = pipChange.getEndAbsBounds().equals(
                mPipBoundsState.getDisplayBounds());
        mFinishCallback = (wct, wctCB) -> {
@@ -518,6 +539,14 @@ public class PipTransition extends PipTransitionController {
                wct.setBounds(pipTaskToken, null);
                mPipOrganizer.applyWindowingModeChangeOnExit(wct, TRANSITION_DIRECTION_LEAVE_PIP);
            }
            if (useLocalLeash) {
                if (mPipAnimationController.isAnimating()) {
                    mPipAnimationController.getCurrentAnimator().end();
                }
                // Make sure the animator don't use the released leash, e.g. mergeAnimation.
                mPipAnimationController.resetAnimatorState();
                finishTransaction.remove(pipLeash);
            }
            finishCallback.onTransitionFinished(wct, wctCB);
        };
        mFinishTransaction = finishTransaction;
@@ -545,7 +574,8 @@ public class PipTransition extends PipTransitionController {
        // Set the initial frame as scaling the end to the start.
        final Rect destinationBounds = new Rect(pipChange.getEndAbsBounds());
        destinationBounds.offset(-offset.x, -offset.y);
        startTransaction.setWindowCrop(pipLeash, destinationBounds);
        startTransaction.setWindowCrop(pipLeash, destinationBounds.width(),
                destinationBounds.height());
        mSurfaceTransactionHelper.scale(startTransaction, pipLeash, destinationBounds,
                currentBounds);
        startTransaction.apply();