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

Commit 5f59127c authored by Chris Li's avatar Chris Li
Browse files

Enter PIP when exiting prev PIP with Shell transition

Before, the dismissPip() is not collected in the enter PIP transition.
Now, the Task that leaving PIP windowing mode will also be part of the
TRANSIT_PIP transition.

Fix: 213300721
Test: manual test with two Pip apps
Change-Id: Iaab34a7969ff4cb5d9768754d643d5f32913f57a
parent f413c130
Loading
Loading
Loading
Loading
+42 −25
Original line number Diff line number Diff line
@@ -175,14 +175,25 @@ public class PipTransition extends PipTransitionController {
            return true;
        }

        // The previous PIP Task is no longer in PIP, but this is not an exit transition (This can
        // happen when a new activity requests enter PIP). In this case, we just show this Task in
        // its end state, and play other animation as normal.
        final TransitionInfo.Change currentPipChange = findCurrentPipChange(info);
        if (currentPipChange != null
                && currentPipChange.getTaskInfo().getWindowingMode() != WINDOWING_MODE_PINNED) {
            resetPrevPip(currentPipChange, startTransaction);
        }

        // Entering PIP.
        if (isEnteringPip(info, mCurrentPipTaskToken)) {
            return startEnterAnimation(info, startTransaction, finishTransaction, finishCallback);
        }

        // For transition that we don't animate, we may need to update the PIP surface, otherwise it
        // will be reset after the transition.
        updatePipForUnhandledTransition(info, startTransaction, finishTransaction);
        // For transition that we don't animate, but contains the PIP leash, we need to update the
        // PIP surface, otherwise it will be reset after the transition.
        if (currentPipChange != null) {
            updatePipForUnhandledTransition(currentPipChange, startTransaction, finishTransaction);
        }
        return false;
    }

@@ -597,20 +608,28 @@ public class PipTransition extends PipTransitionController {
        finishCallback.onTransitionFinished(null, null);
    }

    private void updatePipForUnhandledTransition(@NonNull TransitionInfo info,
    private void resetPrevPip(@NonNull TransitionInfo.Change prevPipChange,
            @NonNull SurfaceControl.Transaction startTransaction) {
        final SurfaceControl leash = prevPipChange.getLeash();
        final Rect bounds = prevPipChange.getEndAbsBounds();
        final Point offset = prevPipChange.getEndRelOffset();
        bounds.offset(-offset.x, -offset.y);

        startTransaction.setWindowCrop(leash, null);
        startTransaction.setMatrix(leash, 1, 0, 0, 1);
        startTransaction.setCornerRadius(leash, 0);
        startTransaction.setPosition(leash, bounds.left, bounds.top);

        mCurrentPipTaskToken = null;
        mPipOrganizer.onExitPipFinished(prevPipChange.getTaskInfo());
    }

    private void updatePipForUnhandledTransition(@NonNull TransitionInfo.Change pipChange,
            @NonNull SurfaceControl.Transaction startTransaction,
            @NonNull SurfaceControl.Transaction finishTransaction) {
        if (mCurrentPipTaskToken == null) {
            return;
        }
        for (int i = info.getChanges().size() - 1; i >= 0; --i) {
            final TransitionInfo.Change change = info.getChanges().get(i);
            if (!mCurrentPipTaskToken.equals(change.getContainer())) {
                continue;
            }
        // When the PIP window is visible and being a part of the transition, such as display
        // rotation, we need to update its bounds and rounded corner.
            final SurfaceControl leash = change.getLeash();
        final SurfaceControl leash = pipChange.getLeash();
        final Rect destBounds = mPipBoundsState.getBounds();
        final boolean isInPip = mPipTransitionState.isInPip();
        mSurfaceTransactionHelper
@@ -619,8 +638,6 @@ public class PipTransition extends PipTransitionController {
        mSurfaceTransactionHelper
                .crop(finishTransaction, leash, destBounds)
                .round(finishTransaction, leash, isInPip);
            break;
        }
    }

    private void finishResizeForMenu(Rect destinationBounds) {
+19 −6
Original line number Diff line number Diff line
@@ -2051,19 +2051,25 @@ class RootWindowContainer extends WindowContainer<DisplayContent>

        try {
            final Task task = r.getTask();
            final Task rootPinnedTask = taskDisplayArea.getRootPinnedTask();

            // This will change the root pinned task's windowing mode to its original mode, ensuring
            // we only have one root task that is in pinned mode.
            // If the activity in current PIP task needs to be moved back to the parent Task of next
            // PIP activity, we can't use that parent Task as the next PIP Task.
            // Because we need to start the Shell transition from the root Task, we delay to dismiss
            // the current PIP task until root Task is ready.
            boolean origPipWillBeMovedToTask = false;
            final Task rootPinnedTask = taskDisplayArea.getRootPinnedTask();
            if (rootPinnedTask != null) {
                rootPinnedTask.dismissPip();
                final ActivityRecord topPipActivity = rootPinnedTask.getTopMostActivity();
                if (topPipActivity != null && topPipActivity.getLastParentBeforePip() == task) {
                    origPipWillBeMovedToTask = true;
                }
            }

            // Set a transition to ensure that we don't immediately try and update the visibility
            // of the activity entering PIP
            r.getDisplayContent().prepareAppTransition(TRANSIT_NONE);

            final boolean singleActivity = task.getChildCount() == 1;
            final boolean singleActivity = task.getChildCount() == 1 && !origPipWillBeMovedToTask;
            final Task rootTask;
            if (singleActivity) {
                rootTask = task;
@@ -2117,7 +2123,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
                final ActivityRecord oldTopActivity = task.getTopMostActivity();
                if (oldTopActivity != null && oldTopActivity.isState(STOPPED)
                        && task.getDisplayContent().mAppTransition.containsTransitRequest(
                        TRANSIT_TO_BACK)) {
                        TRANSIT_TO_BACK) && !origPipWillBeMovedToTask) {
                    task.getDisplayContent().mClosingApps.add(oldTopActivity);
                    oldTopActivity.mRequestForceTransition = true;
                }
@@ -2133,6 +2139,13 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
            }
            rootTask.mTransitionController.requestTransitionIfNeeded(TRANSIT_PIP, rootTask);

            // This will change the root pinned task's windowing mode to its original mode, ensuring
            // we only have one root task that is in pinned mode.
            if (rootPinnedTask != null) {
                rootTask.mTransitionController.collect(rootPinnedTask);
                rootPinnedTask.dismissPip();
            }

            // Defer the windowing mode change until after the transition to prevent the activity
            // from doing work and changing the activity visuals while animating
            // TODO(task-org): Figure-out more structured way to do this long term.