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

Commit 803a4a5b authored by Jeremy Sim's avatar Jeremy Sim
Browse files

Fix bug with over-expanding split task tile

This CL changes GroupedTaskView#onMeasure() to return more robustly in the case where a single task from a GroupedTaskView is staged.

See bug for fine details, but basically we no longer allow onMeasure() to re-bound the split task to fullsize in split selection state -- we leave it in half size all the time (with scale and translation applied). To allow it to stay scaled-up and translated properly across rotations and stuff, we now avoid resetting translation and scale until split select is exited.

Fixes: 365476600
Test: Manual test with offscreen tiles, rotations, fake landscape and seascape
Flag: NONE bugfix
Change-Id: I0ee8d13d310ed1f134f3f396bb87541a5ea685ef
parent 98d85d6d
Loading
Loading
Loading
Loading
+12 −2
Original line number Diff line number Diff line
@@ -453,6 +453,10 @@ open class LandscapePagedViewHandler : RecentsPagedOrientationHandler {
        }
    }

    /**
     * @param inSplitSelection Whether user currently has a task from this task group staged for
     * split screen. Currently this state is not reachable in fake landscape.
     */
    override fun measureGroupedTaskViewThumbnailBounds(
        primarySnapshot: View,
        secondarySnapshot: View,
@@ -460,7 +464,8 @@ open class LandscapePagedViewHandler : RecentsPagedOrientationHandler {
        parentHeight: Int,
        splitBoundsConfig: SplitBounds,
        dp: DeviceProfile,
        isRtl: Boolean
        isRtl: Boolean,
        inSplitSelection: Boolean
    ) {
        val primaryParams = primarySnapshot.layoutParams as FrameLayout.LayoutParams
        val secondaryParams = secondarySnapshot.layoutParams as FrameLayout.LayoutParams
@@ -569,6 +574,10 @@ open class LandscapePagedViewHandler : RecentsPagedOrientationHandler {
        iconAppChipView.setRotation(degreesRotated)
    }

    /**
     * @param inSplitSelection Whether user currently has a task from this task group staged for
     * split screen. Currently this state is not reachable in fake landscape.
     */
    override fun setSplitIconParams(
        primaryIconView: View,
        secondaryIconView: View,
@@ -579,7 +588,8 @@ open class LandscapePagedViewHandler : RecentsPagedOrientationHandler {
        groupedTaskViewWidth: Int,
        isRtl: Boolean,
        deviceProfile: DeviceProfile,
        splitConfig: SplitBounds
        splitConfig: SplitBounds,
        inSplitSelection: Boolean
    ) {
        val spaceAboveSnapshot = deviceProfile.overviewTaskThumbnailTopMarginPx
        val totalThumbnailHeight = groupedTaskViewHeight - spaceAboveSnapshot
+87 −64
Original line number Diff line number Diff line
@@ -530,10 +530,16 @@ public class PortraitPagedViewHandler extends DefaultPagedViewHandler implements
        }
    }

    /**
     * @param inSplitSelection Whether user currently has a task from this task group staged for
     *                         split screen. If true, we have custom translations/scaling in place
     *                         for the remaining snapshot, so we'll skip setting translation/scale
     *                         here.
     */
    @Override
    public void measureGroupedTaskViewThumbnailBounds(View primarySnapshot, View secondarySnapshot,
            int parentWidth, int parentHeight, SplitBounds splitBoundsConfig,
            DeviceProfile dp, boolean isRtl) {
            DeviceProfile dp, boolean isRtl, boolean inSplitSelection) {
        int spaceAboveSnapshot = dp.overviewTaskThumbnailTopMarginPx;

        FrameLayout.LayoutParams primaryParams =
@@ -541,11 +547,10 @@ public class PortraitPagedViewHandler extends DefaultPagedViewHandler implements
        FrameLayout.LayoutParams secondaryParams =
                (FrameLayout.LayoutParams) secondarySnapshot.getLayoutParams();

        // Reset margin and translations that aren't used in this method, but are used in other
        // Reset margins that aren't used in this method, but are used in other
        // `RecentsPagedOrientationHandler` variants.
        secondaryParams.topMargin = 0;
        primaryParams.topMargin = spaceAboveSnapshot;
        primarySnapshot.setTranslationY(0);

        int totalThumbnailHeight = parentHeight - spaceAboveSnapshot;
        float dividerScale = splitBoundsConfig.appsStackedVertically
@@ -553,6 +558,11 @@ public class PortraitPagedViewHandler extends DefaultPagedViewHandler implements
                : splitBoundsConfig.dividerWidthPercent;
        Pair<Point, Point> taskViewSizes =
                getGroupedTaskViewSizes(dp, splitBoundsConfig, parentWidth, parentHeight);
        if (!inSplitSelection) {
            // Reset translations that aren't used in this method, but are used in other
            // `RecentsPagedOrientationHandler` variants.
            primarySnapshot.setTranslationY(0);

            if (dp.isLeftRightSplit) {
                int scaledDividerBar = Math.round(parentWidth * dividerScale);
                if (isRtl) {
@@ -564,17 +574,19 @@ public class PortraitPagedViewHandler extends DefaultPagedViewHandler implements
                    secondarySnapshot.setTranslationX(translationX);
                    primarySnapshot.setTranslationX(0);
                }

                secondarySnapshot.setTranslationY(spaceAboveSnapshot);
            } else {
                float finalDividerHeight = Math.round(totalThumbnailHeight * dividerScale);
            float translationY = taskViewSizes.first.y + spaceAboveSnapshot + finalDividerHeight;
                float translationY =
                        taskViewSizes.first.y + spaceAboveSnapshot + finalDividerHeight;
                secondarySnapshot.setTranslationY(translationY);

                // Reset unused translations.
                secondarySnapshot.setTranslationX(0);
                primarySnapshot.setTranslationX(0);
            }
        }

        primarySnapshot.measure(
                View.MeasureSpec.makeMeasureSpec(taskViewSizes.first.x, View.MeasureSpec.EXACTLY),
                View.MeasureSpec.makeMeasureSpec(taskViewSizes.first.y, View.MeasureSpec.EXACTLY));
@@ -582,10 +594,6 @@ public class PortraitPagedViewHandler extends DefaultPagedViewHandler implements
                View.MeasureSpec.makeMeasureSpec(taskViewSizes.second.x, View.MeasureSpec.EXACTLY),
                View.MeasureSpec.makeMeasureSpec(taskViewSizes.second.y,
                        View.MeasureSpec.EXACTLY));
        primarySnapshot.setScaleX(1);
        secondarySnapshot.setScaleX(1);
        primarySnapshot.setScaleY(1);
        secondarySnapshot.setScaleY(1);
    }

    @Override
@@ -662,11 +670,16 @@ public class PortraitPagedViewHandler extends DefaultPagedViewHandler implements
        iconAppChipView.setRotation(getDegreesRotated());
    }

    /**
     * @param inSplitSelection Whether user currently has a task from this task group staged for
     *                         split screen. If true, we have custom translations in place for the
     *                         remaining icon, so we'll skip setting translations here.
     */
    @Override
    public void setSplitIconParams(View primaryIconView, View secondaryIconView,
            int taskIconHeight, int primarySnapshotWidth, int primarySnapshotHeight,
            int groupedTaskViewHeight, int groupedTaskViewWidth, boolean isRtl,
            DeviceProfile deviceProfile, SplitBounds splitConfig) {
            DeviceProfile deviceProfile, SplitBounds splitConfig, boolean inSplitSelection) {
        FrameLayout.LayoutParams primaryIconParams =
                (FrameLayout.LayoutParams) primaryIconView.getLayoutParams();
        FrameLayout.LayoutParams secondaryIconParams = enableOverviewIconMenu()
@@ -680,6 +693,7 @@ public class PortraitPagedViewHandler extends DefaultPagedViewHandler implements
            secondaryIconParams.gravity = TOP | START;
            secondaryIconParams.topMargin = primaryIconParams.topMargin;
            secondaryIconParams.setMarginStart(primaryIconParams.getMarginStart());
            if (!inSplitSelection) {
                if (deviceProfile.isLeftRightSplit) {
                    if (isRtl) {
                        int secondarySnapshotWidth = groupedTaskViewWidth - primarySnapshotWidth;
@@ -693,7 +707,9 @@ public class PortraitPagedViewHandler extends DefaultPagedViewHandler implements
                    int dividerThickness = Math.min(splitConfig.visualDividerBounds.width(),
                            splitConfig.visualDividerBounds.height());
                    secondaryAppChipView.setSplitTranslationY(
                        primarySnapshotHeight + (deviceProfile.isTablet ? 0 : dividerThickness));
                            primarySnapshotHeight + (deviceProfile.isTablet ? 0
                                    : dividerThickness));
                }
            }
        } else if (deviceProfile.isLeftRightSplit) {
            // We calculate the "midpoint" of the thumbnail area, and place the icons there.
@@ -716,6 +732,7 @@ public class PortraitPagedViewHandler extends DefaultPagedViewHandler implements
            if (deviceProfile.isSeascape()) {
                primaryIconParams.gravity = TOP | (isRtl ? END : START);
                secondaryIconParams.gravity = TOP | (isRtl ? END : START);
                if (!inSplitSelection) {
                    if (splitConfig.initiatedFromSeascape) {
                        // if the split was initiated from seascape,
                        // the task on the right (secondary) is slightly larger
@@ -728,9 +745,11 @@ public class PortraitPagedViewHandler extends DefaultPagedViewHandler implements
                                - taskIconHeight);
                        secondaryIconView.setTranslationX(bottomToMidpointOffset + insetOffset);
                    }
                }
            } else {
                primaryIconParams.gravity = TOP | (isRtl ? START : END);
                secondaryIconParams.gravity = TOP | (isRtl ? START : END);
                if (!inSplitSelection) {
                    if (!splitConfig.initiatedFromSeascape) {
                        // if the split was initiated from landscape,
                        // the task on the left (primary) is slightly larger
@@ -744,18 +763,22 @@ public class PortraitPagedViewHandler extends DefaultPagedViewHandler implements
                                + taskIconHeight);
                    }
                }
            }
        } else {
            primaryIconParams.gravity = TOP | CENTER_HORIZONTAL;
            secondaryIconParams.gravity = TOP | CENTER_HORIZONTAL;
            if (!inSplitSelection) {
                // shifts icon half a width left (height is used here since icons are square)
                primaryIconView.setTranslationX(-(taskIconHeight / 2f));
            secondaryIconParams.gravity = TOP | CENTER_HORIZONTAL;
                secondaryIconView.setTranslationX(taskIconHeight / 2f);
            }
        if (!enableOverviewIconMenu()) {
        }
        if (!enableOverviewIconMenu() && !inSplitSelection) {
            primaryIconView.setTranslationY(0);
            secondaryIconView.setTranslationY(0);
        }


        primaryIconView.setLayoutParams(primaryIconParams);
        secondaryIconView.setLayoutParams(secondaryIconParams);
    }
+4 −2
Original line number Diff line number Diff line
@@ -184,7 +184,8 @@ interface RecentsPagedOrientationHandler : PagedOrientationHandler {
        parentHeight: Int,
        splitBoundsConfig: SplitConfigurationOptions.SplitBounds,
        dp: DeviceProfile,
        isRtl: Boolean
        isRtl: Boolean,
        inSplitSelection: Boolean
    )

    /**
@@ -235,7 +236,8 @@ interface RecentsPagedOrientationHandler : PagedOrientationHandler {
        groupedTaskViewWidth: Int,
        isRtl: Boolean,
        deviceProfile: DeviceProfile,
        splitConfig: SplitConfigurationOptions.SplitBounds
        splitConfig: SplitConfigurationOptions.SplitBounds,
        inSplitSelection: Boolean
    )

    /*
+6 −1
Original line number Diff line number Diff line
@@ -277,6 +277,10 @@ class SeascapePagedViewHandler : LandscapePagedViewHandler() {
        iconAppChipView.setRotation(degreesRotated)
    }

    /**
     * @param inSplitSelection Whether user currently has a task from this task group staged for
     * split screen. Currently this state is not reachable in fake seascape.
     */
    override fun measureGroupedTaskViewThumbnailBounds(
        primarySnapshot: View,
        secondarySnapshot: View,
@@ -284,7 +288,8 @@ class SeascapePagedViewHandler : LandscapePagedViewHandler() {
        parentHeight: Int,
        splitBoundsConfig: SplitBounds,
        dp: DeviceProfile,
        isRtl: Boolean
        isRtl: Boolean,
        inSplitSelection: Boolean
    ) {
        val primaryParams = primarySnapshot.layoutParams as FrameLayout.LayoutParams
        val secondaryParams = secondarySnapshot.layoutParams as FrameLayout.LayoutParams
+19 −5
Original line number Diff line number Diff line
@@ -42,6 +42,8 @@ import android.window.TransitionInfo
import android.window.TransitionInfo.Change
import android.window.WindowContainerToken
import androidx.annotation.VisibleForTesting
import androidx.core.util.component1
import androidx.core.util.component2
import com.android.app.animation.Interpolators
import com.android.launcher3.DeviceProfile
import com.android.launcher3.Flags.enableOverviewIconMenu
@@ -225,10 +227,22 @@ class SplitAnimationController(val splitSelectStateController: SplitSelectStateC
                ObjectAnimator.ofFloat(iconView.splitTranslationY, MULTI_PROPERTY_VALUE, 0f)
            )
        }

        val splitBoundsConfig =
            (taskContainer.taskView as? GroupedTaskView)?.splitBoundsConfig ?: return
        val (primarySnapshotViewSize, secondarySnapshotViewSize) =
            taskContainer.taskView.pagedOrientationHandler.getGroupedTaskViewSizes(
                deviceProfile,
                splitBoundsConfig,
                taskViewWidth,
                taskViewHeight,
            )
        val snapshotViewSize =
            if (isPrimaryTaskSplitting) primarySnapshotViewSize else secondarySnapshotViewSize
        if (deviceProfile.isLeftRightSplit) {
            // Center view first so scaling happens uniformly, alternatively we can move pivotX to 0
            val centerThumbnailTranslationX: Float = (taskViewWidth - snapshot.width) / 2f
            val finalScaleX: Float = taskViewWidth.toFloat() / snapshot.width
            val centerThumbnailTranslationX: Float = (taskViewWidth - snapshotViewSize.x) / 2f
            val finalScaleX: Float = taskViewWidth.toFloat() / snapshotViewSize.x
            builder.add(
                ObjectAnimator.ofFloat(snapshot, View.TRANSLATION_X, centerThumbnailTranslationX)
            )
@@ -262,13 +276,13 @@ class SplitAnimationController(val splitSelectStateController: SplitSelectStateC
            //  thumbnail needs to take that into account. We should migrate to only using
            //  translations otherwise this asymmetry causes problems..
            if (isPrimaryTaskSplitting) {
                centerThumbnailTranslationY = (thumbnailSize - snapshot.height) / 2f
                centerThumbnailTranslationY = (thumbnailSize - snapshotViewSize.y) / 2f
                centerThumbnailTranslationY +=
                    deviceProfile.overviewTaskThumbnailTopMarginPx.toFloat()
            } else {
                centerThumbnailTranslationY = (thumbnailSize - snapshot.height) / 2f
                centerThumbnailTranslationY = (thumbnailSize - snapshotViewSize.y) / 2f
            }
            val finalScaleY: Float = thumbnailSize.toFloat() / snapshot.height
            val finalScaleY: Float = thumbnailSize.toFloat() / snapshotViewSize.y
            builder.add(
                ObjectAnimator.ofFloat(snapshot, View.TRANSLATION_Y, centerThumbnailTranslationY)
            )
Loading