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

Commit 53a48bf6 authored by Jiaming Liu's avatar Jiaming Liu
Browse files

[Divider] Fix wrong drag handle position for RTL layout

Fix miscalculation of the drag handle postion when secondary container
is fully expanded in RTL and BTT layout directions. Also did code clean
up during the fix.

Bug: 343307918
Test: atest DividerPresenter
Change-Id: I3036773255554567d8961a5cd8ee5cd47118aab2
parent df5244aa
Loading
Loading
Loading
Loading
+68 −69
Original line number Diff line number Diff line
@@ -200,6 +200,10 @@ class DividerPresenter implements View.OnTouchListener {
            }

            // At this point, a divider is required.
            final TaskFragmentContainer primaryContainer =
                    topSplitContainer.getPrimaryContainer();
            final TaskFragmentContainer secondaryContainer =
                    topSplitContainer.getSecondaryContainer();

            // Create the decor surface if one is not available yet.
            final SurfaceControl decorSurface = parentInfo.getDecorSurface();
@@ -207,41 +211,44 @@ class DividerPresenter implements View.OnTouchListener {
                // Clean up when the decor surface is currently unavailable.
                removeDivider();
                // Request to create the decor surface
                createOrMoveDecorSurfaceLocked(wct, topSplitContainer.getPrimaryContainer());
                createOrMoveDecorSurfaceLocked(wct, primaryContainer);
                return;
            }

            // Update the decor surface owner if needed.
            boolean isDraggableExpandType =
                    SplitAttributesHelper.isDraggableExpandType(splitAttributes);
            final TaskFragmentContainer decorSurfaceOwnerContainer = isDraggableExpandType
                    ? topSplitContainer.getSecondaryContainer()
                    : topSplitContainer.getPrimaryContainer();
            final TaskFragmentContainer decorSurfaceOwnerContainer =
                    isDraggableExpandType ? secondaryContainer : primaryContainer;

            if (!Objects.equals(
                    mDecorSurfaceOwner, decorSurfaceOwnerContainer.getTaskFragmentToken())) {
                createOrMoveDecorSurfaceLocked(wct, decorSurfaceOwnerContainer);
            }
            final boolean isVerticalSplit = isVerticalSplit(topSplitContainer);
            final boolean isReversedLayout = isReversedLayout(
                    topSplitContainer.getCurrentSplitAttributes(),
                    parentInfo.getConfiguration());

            final Configuration parentConfiguration = parentInfo.getConfiguration();
            final Rect taskBounds = parentConfiguration.windowConfiguration.getBounds();
            final boolean isVerticalSplit = isVerticalSplit(splitAttributes);
            final boolean isReversedLayout = isReversedLayout(splitAttributes, parentConfiguration);
            final int dividerWidthPx = getDividerWidthPx(dividerAttributes);

            updateProperties(
                    new Properties(
                            parentInfo.getConfiguration(),
                            parentConfiguration,
                            dividerAttributes,
                            decorSurface,
                            getInitialDividerPosition(
                                    topSplitContainer, isVerticalSplit, isReversedLayout),
                                    primaryContainer, secondaryContainer, taskBounds,
                                    dividerWidthPx, isDraggableExpandType, isVerticalSplit,
                                    isReversedLayout),
                            isVerticalSplit,
                            isReversedLayout,
                            parentInfo.getDisplayId(),
                            isDraggableExpandType,
                            getContainerBackgroundColor(topSplitContainer.getPrimaryContainer(),
                                    DEFAULT_PRIMARY_VEIL_COLOR),
                            getContainerBackgroundColor(topSplitContainer.getSecondaryContainer(),
                                    DEFAULT_SECONDARY_VEIL_COLOR)
                            getContainerBackgroundColor(
                                    primaryContainer, DEFAULT_PRIMARY_VEIL_COLOR),
                            getContainerBackgroundColor(
                                    secondaryContainer, DEFAULT_SECONDARY_VEIL_COLOR)
                    ));
        }
    }
@@ -338,32 +345,31 @@ class DividerPresenter implements View.OnTouchListener {

    @VisibleForTesting
    static int getInitialDividerPosition(
            @NonNull SplitContainer splitContainer,
            @NonNull TaskFragmentContainer primaryContainer,
            @NonNull TaskFragmentContainer secondaryContainer,
            @NonNull Rect taskBounds,
            int dividerWidthPx,
            boolean isDraggableExpandType,
            boolean isVerticalSplit,
            boolean isReversedLayout) {
        final Rect primaryBounds =
                splitContainer.getPrimaryContainer().getLastRequestedBounds();
        final Rect secondaryBounds =
                splitContainer.getSecondaryContainer().getLastRequestedBounds();
        final SplitAttributes splitAttributes = splitContainer.getCurrentSplitAttributes();

        if (SplitAttributesHelper.isDraggableExpandType(splitAttributes)) {
            // If the container is fully expanded by dragging the divider, we display the divider
            // on the edge.
            final int dividerWidth = getDividerWidthPx(splitAttributes.getDividerAttributes());
        if (isDraggableExpandType) {
            // If the secondary container is fully expanded by dragging the divider, we display the
            // divider on the edge.
            final int fullyExpandedPosition = isVerticalSplit
                    ? primaryBounds.right - dividerWidth
                    : primaryBounds.bottom - dividerWidth;
                    ? taskBounds.width() - dividerWidthPx
                    : taskBounds.height() - dividerWidthPx;
            return isReversedLayout ? fullyExpandedPosition : 0;
        } else {
            final Rect primaryBounds = primaryContainer.getLastRequestedBounds();
            final Rect secondaryBounds = secondaryContainer.getLastRequestedBounds();
            return isVerticalSplit
                    ? Math.min(primaryBounds.right, secondaryBounds.right)
                    : Math.min(primaryBounds.bottom, secondaryBounds.bottom);
        }
    }

    private static boolean isVerticalSplit(@NonNull SplitContainer splitContainer) {
        final int layoutDirection = splitContainer.getCurrentSplitAttributes().getLayoutDirection();
    private static boolean isVerticalSplit(@NonNull SplitAttributes splitAttributes) {
        final int layoutDirection = splitAttributes.getLayoutDirection();
        switch (layoutDirection) {
            case SplitAttributes.LayoutDirection.LEFT_TO_RIGHT:
            case SplitAttributes.LayoutDirection.RIGHT_TO_LEFT:
@@ -510,7 +516,7 @@ class DividerPresenter implements View.OnTouchListener {
            if (mProperties != null && mRenderer != null) {
                final Rect taskBounds = mProperties.mConfiguration.windowConfiguration.getBounds();
                mDividerPosition = calculateDividerPosition(
                        event, taskBounds, mRenderer.mDividerWidthPx,
                        event, taskBounds, mProperties.mDividerWidthPx,
                        mProperties.mDividerAttributes, mProperties.mIsVerticalSplit,
                        calculateMinPosition(), calculateMaxPosition());
                mRenderer.setDividerPosition(mDividerPosition);
@@ -671,8 +677,8 @@ class DividerPresenter implements View.OnTouchListener {
        final int minPosition = calculateMinPosition();
        final int maxPosition = calculateMaxPosition();
        final int fullyExpandedPosition = mProperties.mIsVerticalSplit
                ? taskBounds.right - mRenderer.mDividerWidthPx
                : taskBounds.bottom - mRenderer.mDividerWidthPx;
                ? taskBounds.width() - mProperties.mDividerWidthPx
                : taskBounds.height() - mProperties.mDividerWidthPx;

        if (isDraggingToFullscreenAllowed(mProperties.mDividerAttributes)) {
            final float displayDensity = getDisplayDensity();
@@ -777,7 +783,7 @@ class DividerPresenter implements View.OnTouchListener {
    private int calculateMinPosition() {
        return calculateMinPosition(
                mProperties.mConfiguration.windowConfiguration.getBounds(),
                mRenderer.mDividerWidthPx, mProperties.mDividerAttributes,
                mProperties.mDividerWidthPx, mProperties.mDividerAttributes,
                mProperties.mIsVerticalSplit, mProperties.mIsReversedLayout);
    }

@@ -785,7 +791,7 @@ class DividerPresenter implements View.OnTouchListener {
    private int calculateMaxPosition() {
        return calculateMaxPosition(
                mProperties.mConfiguration.windowConfiguration.getBounds(),
                mRenderer.mDividerWidthPx, mProperties.mDividerAttributes,
                mProperties.mDividerWidthPx, mProperties.mDividerAttributes,
                mProperties.mIsVerticalSplit, mProperties.mIsReversedLayout);
    }

@@ -823,13 +829,12 @@ class DividerPresenter implements View.OnTouchListener {
     * Returns the new split ratio of the {@link SplitContainer} based on the current divider
     * position.
     */
    float calculateNewSplitRatio(@NonNull SplitContainer topSplitContainer) {
    float calculateNewSplitRatio() {
        synchronized (mLock) {
            return calculateNewSplitRatio(
                    topSplitContainer,
                    mDividerPosition,
                    mProperties.mConfiguration.windowConfiguration.getBounds(),
                    mRenderer.mDividerWidthPx,
                    mProperties.mDividerWidthPx,
                    mProperties.mIsVerticalSplit,
                    mProperties.mIsReversedLayout,
                    calculateMinPosition(),
@@ -849,13 +854,12 @@ class DividerPresenter implements View.OnTouchListener {
     * Returns the new split ratio of the {@link SplitContainer} based on the current divider
     * position.
     *
     * @param topSplitContainer the {@link SplitContainer} for which to compute the split ratio.
     * @param dividerPosition the divider position. See {@link #mDividerPosition}.
     * @param taskBounds the task bounds
     * @param dividerWidthPx the width of the divider in pixels.
     * @param isVerticalSplit if {@code true}, the split is a vertical split. If {@code false}, the
     *                        split is a horizontal split. See
     *                        {@link #isVerticalSplit(SplitContainer)}.
     *                        {@link #isVerticalSplit(SplitAttributes)}.
     * @param isReversedLayout if {@code true}, the split layout is reversed, i.e. right-to-left or
     *                         bottom-to-top. If {@code false}, the split is not reversed, i.e.
     *                         left-to-right or top-to-bottom. See
@@ -866,7 +870,6 @@ class DividerPresenter implements View.OnTouchListener {
     */
    @VisibleForTesting
    static float calculateNewSplitRatio(
            @NonNull SplitContainer topSplitContainer,
            int dividerPosition,
            @NonNull Rect taskBounds,
            int dividerWidthPx,
@@ -891,8 +894,6 @@ class DividerPresenter implements View.OnTouchListener {
            dividerPosition = Math.clamp(dividerPosition, minPosition, maxPosition);
        }

        final TaskFragmentContainer primaryContainer = topSplitContainer.getPrimaryContainer();
        final Rect origPrimaryBounds = primaryContainer.getLastRequestedBounds();
        final int usableSize = isVerticalSplit
                ? taskBounds.width() - dividerWidthPx
                : taskBounds.height() - dividerWidthPx;
@@ -900,13 +901,13 @@ class DividerPresenter implements View.OnTouchListener {
        final float newRatio;
        if (isVerticalSplit) {
            final int newPrimaryWidth = isReversedLayout
                    ? (origPrimaryBounds.right - (dividerPosition + dividerWidthPx))
                    : (dividerPosition - origPrimaryBounds.left);
                    ? taskBounds.width() - (dividerPosition + dividerWidthPx)
                    : dividerPosition;
            newRatio = 1.0f * newPrimaryWidth / usableSize;
        } else {
            final int newPrimaryHeight = isReversedLayout
                    ? (origPrimaryBounds.bottom - (dividerPosition + dividerWidthPx))
                    : (dividerPosition - origPrimaryBounds.top);
                    ? taskBounds.height() - (dividerPosition + dividerWidthPx)
                    : dividerPosition;
            newRatio = 1.0f * newPrimaryHeight / usableSize;
        }
        return newRatio;
@@ -961,6 +962,7 @@ class DividerPresenter implements View.OnTouchListener {
        private final boolean mIsDraggableExpandType;
        private final Color mPrimaryVeilColor;
        private final Color mSecondaryVeilColor;
        private final int mDividerWidthPx;

        @VisibleForTesting
        Properties(
@@ -984,6 +986,7 @@ class DividerPresenter implements View.OnTouchListener {
            mIsDraggableExpandType = isDraggableExpandType;
            mPrimaryVeilColor = primaryVeilColor;
            mSecondaryVeilColor = secondaryVeilColor;
            mDividerWidthPx = getDividerWidthPx(dividerAttributes);
        }

        /**
@@ -1050,7 +1053,6 @@ class DividerPresenter implements View.OnTouchListener {
        private final View.OnTouchListener mListener;
        @NonNull
        private Properties mProperties;
        private int mDividerWidthPx;
        private int mHandleWidthPx;
        @Nullable
        private SurfaceControl mPrimaryVeil;
@@ -1090,7 +1092,6 @@ class DividerPresenter implements View.OnTouchListener {
        /** Updates the divider when initializing or when properties are changed */
        @VisibleForTesting
        void update() {
            mDividerWidthPx = getDividerWidthPx(mProperties.mDividerAttributes);
            mDividerPosition = mProperties.mInitialDividerPosition;
            mWindowlessWindowManager.setConfiguration(mProperties.mConfiguration);

@@ -1156,15 +1157,17 @@ class DividerPresenter implements View.OnTouchListener {
                // When the divider drag handle width is larger than the divider width, the position
                // of the divider surface is adjusted so that it is large enough to host both the
                // divider line and the divider drag handle.
                mDividerSurfaceWidthPx = Math.max(mDividerWidthPx, mHandleWidthPx);
                dividerSurfacePosition =
                        mProperties.mIsReversedLayout
                mDividerSurfaceWidthPx = Math.max(mProperties.mDividerWidthPx, mHandleWidthPx);
                dividerSurfacePosition = mProperties.mIsReversedLayout
                        ? mDividerPosition
                                : mDividerPosition + mDividerWidthPx - mDividerSurfaceWidthPx;
                dividerSurfacePosition = Math.clamp(dividerSurfacePosition, 0,
                        mProperties.mIsVerticalSplit ? taskBounds.width() : taskBounds.height());
                        : mDividerPosition + mProperties.mDividerWidthPx - mDividerSurfaceWidthPx;
                dividerSurfacePosition =
                        Math.clamp(dividerSurfacePosition, 0,
                                mProperties.mIsVerticalSplit
                                        ? taskBounds.width() - mDividerSurfaceWidthPx
                                        : taskBounds.height() - mDividerSurfaceWidthPx);
            } else {
                mDividerSurfaceWidthPx = mDividerWidthPx;
                mDividerSurfaceWidthPx = mProperties.mDividerWidthPx;
                dividerSurfacePosition = mDividerPosition;
            }

@@ -1177,16 +1180,9 @@ class DividerPresenter implements View.OnTouchListener {
            }

            // Update divider line position in the surface
            if (!mProperties.mIsReversedLayout) {
            final int offset = mDividerPosition - dividerSurfacePosition;
            mDividerLine.setX(mProperties.mIsVerticalSplit ? offset : 0);
            mDividerLine.setY(mProperties.mIsVerticalSplit ? 0 : offset);
            } else {
                // For reversed layout, the divider line is always at the start of the divider
                // surface.
                mDividerLine.setX(0);
                mDividerLine.setY(0);
            }

            if (mIsDragging) {
                updateVeils(t);
@@ -1236,8 +1232,10 @@ class DividerPresenter implements View.OnTouchListener {
            final Rect taskBounds = mProperties.mConfiguration.windowConfiguration.getBounds();
            mDividerLine.setLayoutParams(
                    mProperties.mIsVerticalSplit
                            ? new FrameLayout.LayoutParams(mDividerWidthPx, taskBounds.height())
                            : new FrameLayout.LayoutParams(taskBounds.width(), mDividerWidthPx)
                            ? new FrameLayout.LayoutParams(
                                    mProperties.mDividerWidthPx, taskBounds.height())
                            : new FrameLayout.LayoutParams(
                                    taskBounds.width(), mProperties.mDividerWidthPx)
            );
            if (mProperties.mDividerAttributes.getDividerType()
                    == DividerAttributes.DIVIDER_TYPE_DRAGGABLE) {
@@ -1347,13 +1345,14 @@ class DividerPresenter implements View.OnTouchListener {
            Rect secondaryBounds;
            if (mProperties.mIsVerticalSplit) {
                final Rect boundsLeft = new Rect(0, 0, mDividerPosition, taskBounds.height());
                final Rect boundsRight = new Rect(mDividerPosition + mDividerWidthPx, 0,
                final Rect boundsRight = new Rect(mDividerPosition + mProperties.mDividerWidthPx, 0,
                        taskBounds.width(), taskBounds.height());
                primaryBounds = mProperties.mIsReversedLayout ? boundsRight : boundsLeft;
                secondaryBounds = mProperties.mIsReversedLayout ? boundsLeft : boundsRight;
            } else {
                final Rect boundsTop = new Rect(0, 0, taskBounds.width(), mDividerPosition);
                final Rect boundsBottom = new Rect(0, mDividerPosition + mDividerWidthPx,
                final Rect boundsBottom = new Rect(
                        0, mDividerPosition + mProperties.mDividerWidthPx,
                        taskBounds.width(), taskBounds.height());
                primaryBounds = mProperties.mIsReversedLayout ? boundsBottom : boundsTop;
                secondaryBounds = mProperties.mIsReversedLayout ? boundsTop : boundsBottom;
+1 −1
Original line number Diff line number Diff line
@@ -510,7 +510,7 @@ class TaskContainer {
            return;
        }
        final TaskFragmentContainer primaryContainer = topSplitContainer.getPrimaryContainer();
        final float newRatio = dividerPresenter.calculateNewSplitRatio(topSplitContainer);
        final float newRatio = dividerPresenter.calculateNewSplitRatio();

        // If the primary container is fully expanded, we should finish all the associated
        // secondary containers.
+4 −7
Original line number Diff line number Diff line
@@ -144,6 +144,7 @@ public class DividerPresenterTest {
                new SplitAttributes.Builder()
                        .setDividerAttributes(DEFAULT_DIVIDER_ATTRIBUTES)
                        .build());
        final Rect mockTaskBounds = new Rect(0, 0, 2000, 1000);
        final TaskFragmentContainer mockPrimaryContainer =
                createMockTaskFragmentContainer(
                        mPrimaryContainerToken, new Rect(0, 0, 950, 1000));
@@ -158,7 +159,9 @@ public class DividerPresenterTest {
                DEFAULT_DIVIDER_ATTRIBUTES,
                mSurfaceControl,
                getInitialDividerPosition(
                        mSplitContainer, true /* isVerticalSplit */, false /* isReversedLayout */),
                        mockPrimaryContainer, mockSecondaryContainer, mockTaskBounds,
                        50 /* divideWidthPx */, false /* isDraggableExpandType */,
                        true /* isVerticalSplit */, false /* isReversedLayout */),
                true /* isVerticalSplit */,
                false /* isReversedLayout */,
                Display.DEFAULT_DISPLAY,
@@ -502,7 +505,6 @@ public class DividerPresenterTest {
        assertEquals(
                0.3f, // Primary is 300px after dragging.
                DividerPresenter.calculateNewSplitRatio(
                        mSplitContainer,
                        dividerPosition,
                        taskBounds,
                        dividerWidthPx,
@@ -518,7 +520,6 @@ public class DividerPresenterTest {
        assertEquals(
                DividerPresenter.RATIO_EXPANDED_SECONDARY,
                DividerPresenter.calculateNewSplitRatio(
                        mSplitContainer,
                        dividerPosition,
                        taskBounds,
                        dividerWidthPx,
@@ -535,7 +536,6 @@ public class DividerPresenterTest {
        assertEquals(
                0.2f, // Adjusted to the minPosition 200
                DividerPresenter.calculateNewSplitRatio(
                        mSplitContainer,
                        dividerPosition,
                        taskBounds,
                        dividerWidthPx,
@@ -569,7 +569,6 @@ public class DividerPresenterTest {
                // After dragging, secondary is [0, 0, 2000, 300]. Primary is [0, 400, 2000, 1100].
                0.7f,
                DividerPresenter.calculateNewSplitRatio(
                        mSplitContainer,
                        dividerPosition,
                        taskBounds,
                        dividerWidthPx,
@@ -587,7 +586,6 @@ public class DividerPresenterTest {
                // The primary (bottom) container is expanded
                DividerPresenter.RATIO_EXPANDED_PRIMARY,
                DividerPresenter.calculateNewSplitRatio(
                        mSplitContainer,
                        dividerPosition,
                        taskBounds,
                        dividerWidthPx,
@@ -605,7 +603,6 @@ public class DividerPresenterTest {
                // Adjusted to minPosition 200, so the primary (bottom) container is 800.
                0.8f,
                DividerPresenter.calculateNewSplitRatio(
                        mSplitContainer,
                        dividerPosition,
                        taskBounds,
                        dividerWidthPx,