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

Commit d3c0833e authored by Jeremy Sim's avatar Jeremy Sim
Browse files

Add smooth dimming transition for swapping in flexible split

Animates the dim layer during the swap movement, so that dimmed offscreen apps gradually become brighter as they come onscreen (and vice versa).

Previously, the shift was abrupt (at the end of the swap movement) and looked bad.

Also adds an API to SplitState to check the onscreen/offscreen status of a given Rect (should be useful later too).

Bug: 349828130
Flag: com.android.wm.shell.enable_flexible_two_app_split
Test: Dim layer transitions nicely when swapping. Doesn't affect onscreen > onscreen case. No change when flag is off.
Change-Id: Ie5133e84967bd4905c192967ecb673adb12bf26d
parent 877f01cf
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -222,6 +222,10 @@ class ResizingEffectPolicy {
        }
    }

    /**
     * Called on every frame while the user is dragging the divider to dismiss an app or move it
     * offscreen. Sets alpha and visibility on the two provided dim layers.
     */
    void adjustDimSurface(SurfaceControl.Transaction t,
            SurfaceControl dimLayer1, SurfaceControl dimLayer2) {
        SurfaceControl targetDimLayer;
+23 −0
Original line number Diff line number Diff line
@@ -1075,6 +1075,9 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange
        final SurfaceControl leash = isApp ? stage.getRootLeash() : getDividerLeash();
        final ActivityManager.RunningTaskInfo taskInfo = isApp ? stage.getRunningTaskInfo() : null;
        final SplitDecorManager decorManager = isApp ? stage.getDecorManager() : null;
        final SurfaceControl dimLayer =  isApp ? stage.getDimLayer() : null;
        boolean goingOffscreen = !mSplitState.isOffscreen(start) && mSplitState.isOffscreen(end);
        boolean comingOnscreen = mSplitState.isOffscreen(start) && !mSplitState.isOffscreen(end);

        Rect tempStart = new Rect(start);
        Rect tempEnd = new Rect(end);
@@ -1196,6 +1199,26 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange
                            taskInfo, mTempRect, t, isGoingBehind, leash, diffOffsetX, diffOffsetY);
                }
            }

            // App surfaces are dimmed when offscreen. So if the app is moving from onscreen to
            // offscreen or vice versa, we set the dim layer's alpha on every frame for a smooth
            // transition.
            if (Flags.enableFlexibleTwoAppSplit() && dimLayer != null) {
                float instantaneousAlpha = 0f;
                if (goingOffscreen) {
                    instantaneousAlpha = moveProgress * ResizingEffectPolicy.DEFAULT_OFFSCREEN_DIM;
                }
                if (comingOnscreen) {
                    instantaneousAlpha =
                            (1f - moveProgress) * ResizingEffectPolicy.DEFAULT_OFFSCREEN_DIM;
                }
                // If neither of these cases is true, we are in a simple onscreen > onscreen case,
                // and we can hide the dim layer. Offscreen > offscreen swaps are not possible
                // currently (and not very likely to ever exist).
                t.setAlpha(dimLayer, instantaneousAlpha);
                t.setVisibility(dimLayer, instantaneousAlpha > 0.001f);
            }

            t.apply();
        });
        return animator;
+8 −0
Original line number Diff line number Diff line
@@ -53,6 +53,8 @@ public class SplitSpec {
    public static final float MIDDLE_RATIO = 0.5f;

    private final boolean mIsLeftRightSplit;
    /** The physical size of the display. */
    private final Rect mDisplayBounds;
    /** The usable display area, considering insets that affect split bounds. */
    private final RectF mUsableArea;
    /** Half the divider size. */
@@ -65,6 +67,7 @@ public class SplitSpec {
    public SplitSpec(Rect displayBounds, int dividerSize, boolean isLeftRightSplit,
            Rect pinnedTaskbarInsets) {
        mIsLeftRightSplit = isLeftRightSplit;
        mDisplayBounds = new Rect(displayBounds);
        mUsableArea = new RectF(displayBounds);
        mUsableArea.left += pinnedTaskbarInsets.left;
        mUsableArea.top += pinnedTaskbarInsets.top;
@@ -180,4 +183,9 @@ public class SplitSpec {
    List<RectF> getSpec(@SplitScreenState int state) {
        return mLayouts.get(state);
    }

    /** Returns whether a given Rect is partially offscreen on the current display. */
    boolean isOffscreen(Rect rect) {
        return !mDisplayBounds.contains(rect);
    }
}
+5 −0
Original line number Diff line number Diff line
@@ -73,6 +73,11 @@ public class SplitState {
        return getLayout(mState);
    }

    /** Returns whether a given Rect is partially offscreen on the current display. */
    boolean isOffscreen(Rect rect) {
        return mSplitSpec.isOffscreen(rect);
    }

    /** @return {@code true} if at least one app is partially offscreen in the current layout. */
    public boolean currentStateSupportsOffscreenApps() {
        return mState == SNAP_TO_2_10_90
+8 −0
Original line number Diff line number Diff line
@@ -193,6 +193,14 @@ public class StageTaskListener implements ShellTaskOrganizer.TaskListener {
        return mSplitDecorManager;
    }

    /**
     * Gets the leash for this task's dim layer. We manipulate this surface's alpha to dim the app
     * when it's moving offscreen or toward dismissal.
     */
    public SurfaceControl getDimLayer() {
        return mDimLayer;
    }

    @Nullable
    private ActivityManager.RunningTaskInfo getChildTaskInfo(
            Predicate<ActivityManager.RunningTaskInfo> predicate) {