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

Commit 8563943b authored by Jorim Jaggi's avatar Jorim Jaggi
Browse files

Fix smallest width configuration calculation

For calculating the smallest width, we need to iterate through all possible
orientations, snap the task bounds to a valid snap target and then use the
smallest width across all orientations.

In addition to that, when flinging the divider handle to the bottom of the
screen, we need to pass in fullscreen task bounds to avoid that this new
logic applies so the maximizing app only receives one configuration change.

Change-Id: I37aa9a40938517dfaf26770eb41327d76aec7c62
Fixes: 28469673
parent dce92891
Loading
Loading
Loading
Loading
+24 −10
Original line number Diff line number Diff line
@@ -246,7 +246,8 @@ public class DividerSnapAlgorithm {
        int dividerMax = isHorizontalDivision
                ? mDisplayHeight
                : mDisplayWidth;
        mTargets.add(new SnapTarget(-mDividerSize, SnapTarget.FLAG_DISMISS_START, 0.35f));
        mTargets.add(new SnapTarget(-mDividerSize, -mDividerSize, SnapTarget.FLAG_DISMISS_START,
                0.35f));
        switch (mSnapMode) {
            case SNAP_MODE_16_9:
                addRatio16_9Targets(isHorizontalDivision, dividerMax);
@@ -259,7 +260,8 @@ public class DividerSnapAlgorithm {
                break;
        }
        int navBarSize = isHorizontalDivision ? mInsets.bottom : mInsets.right;
        mTargets.add(new SnapTarget(dividerMax - navBarSize, SnapTarget.FLAG_DISMISS_END, 0.35f));
        mTargets.add(new SnapTarget(dividerMax - navBarSize, dividerMax,
                SnapTarget.FLAG_DISMISS_END, 0.35f));
    }

    private void addNonDismissingTargets(boolean isHorizontalDivision, int topPosition,
@@ -269,13 +271,15 @@ public class DividerSnapAlgorithm {
        maybeAddTarget(bottomPosition, dividerMax - mInsets.bottom
                - (bottomPosition + mDividerSize));
    }

    private void addFixedDivisionTargets(boolean isHorizontalDivision, int dividerMax) {
        int start = isHorizontalDivision ? mInsets.top : mInsets.left;
        int end = isHorizontalDivision
                ? mDisplayHeight - mInsets.bottom
                : mDisplayWidth - mInsets.right;
        int topPosition = (int) (start + mFixedRatio * (end - start)) - mDividerSize / 2;
        int bottomPosition = (int) (start + (1 - mFixedRatio) * (end - start)) - mDividerSize / 2;
        int size = (int) (mFixedRatio * (end - start)) - mDividerSize / 2;
        int topPosition = start + size;
        int bottomPosition = end - size - mDividerSize;
        addNonDismissingTargets(isHorizontalDivision, topPosition, bottomPosition, dividerMax);
    }

@@ -301,13 +305,14 @@ public class DividerSnapAlgorithm {
     */
    private void maybeAddTarget(int position, int smallerSize) {
        if (smallerSize >= mMinimalSizeResizableTask) {
            mTargets.add(new SnapTarget(position, SnapTarget.FLAG_NONE));
            mTargets.add(new SnapTarget(position, position, SnapTarget.FLAG_NONE));
        }
    }

    private void addMiddleTarget(boolean isHorizontalDivision) {
        mTargets.add(new SnapTarget(DockedDividerUtils.calculateMiddlePosition(isHorizontalDivision,
                mInsets, mDisplayWidth, mDisplayHeight, mDividerSize), SnapTarget.FLAG_NONE));
        int position = DockedDividerUtils.calculateMiddlePosition(isHorizontalDivision,
                mInsets, mDisplayWidth, mDisplayHeight, mDividerSize);
        mTargets.add(new SnapTarget(position, position, SnapTarget.FLAG_NONE));
    }

    public SnapTarget getMiddleTarget() {
@@ -370,7 +375,15 @@ public class DividerSnapAlgorithm {
        /** If the divider reaches this value, the right/bottom task should be dismissed */
        public static final int FLAG_DISMISS_END = 2;

        /** Position of this snap target. The right/bottom edge of the top/left task snaps here. */
        public final int position;

        /**
         * Like {@link #position}, but used to calculate the task bounds which might be different
         * from the stack bounds.
         */
        public final int taskPosition;

        public final int flag;

        /**
@@ -379,12 +392,13 @@ public class DividerSnapAlgorithm {
         */
        private final float distanceMultiplier;

        public SnapTarget(int position, int flag) {
            this(position, flag, 1f);
        public SnapTarget(int position, int taskPosition, int flag) {
            this(position, taskPosition, flag, 1f);
        }

        public SnapTarget(int position, int flag, float distanceMultiplier) {
        public SnapTarget(int position, int taskPosition, int flag, float distanceMultiplier) {
            this.position = position;
            this.taskPosition = taskPosition;
            this.flag = flag;
            this.distanceMultiplier = distanceMultiplier;
        }
+1 −1
Original line number Diff line number Diff line
@@ -535,7 +535,7 @@ public class DividerView extends FrameLayout implements OnTouchListener,
        anim.addUpdateListener(animation -> resizeStack((Integer) animation.getAnimatedValue(),
                taskPositionSameAtEnd && animation.getAnimatedFraction() == 1f
                        ? TASK_POSITION_SAME
                        : snapTarget.position, snapTarget));
                        : snapTarget.taskPosition, snapTarget));
        Runnable endAction = () -> {
            commitSnapFlags(snapTarget);
            mWindowManagerProxy.setResizing(false);
+8 −6
Original line number Diff line number Diff line
@@ -1508,16 +1508,18 @@ final class TaskRecord {
                ? Configuration.ORIENTATION_PORTRAIT
                : Configuration.ORIENTATION_LANDSCAPE;

        // For calculating screen layout and smallest screen width, we need to use the non-decor
        // inset screen area for the calculation for compatibility reasons, i.e. screen area without
        // system bars that could never go away in Honeycomb.
        // For calculating screen layout, we need to use the non-decor inset screen area for the
        // calculation for compatibility reasons, i.e. screen area without system bars that could
        // never go away in Honeycomb.
        final int compatScreenWidthDp = (int)(mTmpNonDecorBounds.width() / density);
        final int compatScreenHeightDp = (int)(mTmpNonDecorBounds.height() / density);
        final int sl = Configuration.resetScreenLayout(serviceConfig.screenLayout);
        final int longSize = Math.max(compatScreenHeightDp, compatScreenWidthDp);
        config.smallestScreenWidthDp = Math.min(compatScreenHeightDp, compatScreenWidthDp);
        config.screenLayout = Configuration.reduceScreenLayout(sl, longSize,
                config.smallestScreenWidthDp);
        final int shortSize = Math.min(compatScreenHeightDp, compatScreenWidthDp);;
        config.screenLayout = Configuration.reduceScreenLayout(sl, longSize, shortSize);

        config.smallestScreenWidthDp = mService.mWindowManager.getSmallestWidthForTaskBounds(
                insetBounds != null ? insetBounds : bounds);
        return config;
    }

+81 −0
Original line number Diff line number Diff line
@@ -19,6 +19,10 @@ package com.android.server.wm;
import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
import static android.view.Surface.ROTATION_270;
import static android.view.Surface.ROTATION_90;
import static android.view.WindowManager.DOCKED_BOTTOM;
import static android.view.WindowManager.DOCKED_LEFT;
import static android.view.WindowManager.DOCKED_RIGHT;
@@ -30,6 +34,7 @@ import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
import static com.android.server.wm.WindowManagerService.H.NOTIFY_DOCKED_STACK_MINIMIZED_CHANGED;

import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Rect;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
@@ -41,6 +46,8 @@ import android.view.animation.AnimationUtils;
import android.view.animation.Interpolator;
import android.view.animation.PathInterpolator;

import com.android.internal.policy.DividerSnapAlgorithm;
import com.android.internal.policy.DockedDividerUtils;
import com.android.server.wm.DimLayer.DimLayerUser;
import com.android.server.wm.WindowManagerService.H;

@@ -96,6 +103,7 @@ public class DockedStackDividerController implements DimLayerUser {
    private WindowState mWindow;
    private final Rect mTmpRect = new Rect();
    private final Rect mTmpRect2 = new Rect();
    private final Rect mTmpRect3 = new Rect();
    private final Rect mLastRect = new Rect();
    private boolean mLastVisibility = false;
    private final RemoteCallbackList<IDockedStackListener> mDockedStackListeners
@@ -121,6 +129,7 @@ public class DockedStackDividerController implements DimLayerUser {
    private float mDividerAnimationTarget;
    private float mLastAnimationProgress;
    private float mLastDividerProgress;
    private final DividerSnapAlgorithm[] mSnapAlgorithmForRotation = new DividerSnapAlgorithm[4];

    DockedStackDividerController(WindowManagerService service, DisplayContent displayContent) {
        mService = service;
@@ -133,6 +142,77 @@ public class DockedStackDividerController implements DimLayerUser {
        loadDimens();
    }

    int getSmallestWidthDpForBounds(Rect bounds) {
        final DisplayInfo di = mDisplayContent.getDisplayInfo();

        // If the bounds are fullscreen, return the value of the fullscreen configuration
        if (bounds == null || (bounds.left == 0 && bounds.top == 0
                && bounds.right == di.logicalWidth && bounds.bottom == di.logicalHeight)) {
            return mService.mCurConfiguration.smallestScreenWidthDp;
        }
        final int baseDisplayWidth = mDisplayContent.mBaseDisplayWidth;
        final int baseDisplayHeight = mDisplayContent.mBaseDisplayHeight;
        int minWidth = Integer.MAX_VALUE;

        // Go through all screen orientations and find the orientation in which the task has the
        // smallest width.
        for (int rotation = 0; rotation < 4; rotation++) {
            mTmpRect.set(bounds);
            mDisplayContent.rotateBounds(di.rotation, rotation, mTmpRect);
            final boolean rotated = (rotation == ROTATION_90 || rotation == ROTATION_270);
            mTmpRect2.set(0, 0,
                    rotated ? baseDisplayHeight : baseDisplayWidth,
                    rotated ? baseDisplayWidth : baseDisplayHeight);
            final int orientation = mTmpRect2.width() <= mTmpRect2.height()
                    ? ORIENTATION_PORTRAIT
                    : ORIENTATION_LANDSCAPE;
            final int dockSide = TaskStack.getDockSideUnchecked(mTmpRect, mTmpRect2, orientation);
            final int position = DockedDividerUtils.calculatePositionForBounds(mTmpRect, dockSide,
                    getContentWidth());

            // Since we only care about feasible states, snap to the closest snap target, like it
            // would happen when actually rotating the screen.
            final int snappedPosition = mSnapAlgorithmForRotation[rotation]
                    .calculateNonDismissingSnapTarget(position).position;
            DockedDividerUtils.calculateBoundsForPosition(snappedPosition, dockSide, mTmpRect,
                    mTmpRect2.width(), mTmpRect2.height(), getContentWidth());
            mService.mPolicy.getStableInsetsLw(rotation, mTmpRect2.width(), mTmpRect2.height(),
                    mTmpRect3);
            mService.subtractInsets(mTmpRect2, mTmpRect3, mTmpRect);
            minWidth = Math.min(mTmpRect.width(), minWidth);
        }
        return (int) (minWidth / mDisplayContent.getDisplayMetrics().density);
    }

    private void initSnapAlgorithmForRotations() {
        final Configuration baseConfig = mService.mCurConfiguration;

        // Initialize the snap algorithms for all 4 screen orientations.
        final Configuration config = new Configuration();
        for (int rotation = 0; rotation < 4; rotation++) {
            final boolean rotated = (rotation == ROTATION_90 || rotation == ROTATION_270);
            final int dw = rotated
                    ? mDisplayContent.mBaseDisplayHeight
                    : mDisplayContent.mBaseDisplayWidth;
            final int dh = rotated
                    ? mDisplayContent.mBaseDisplayWidth
                    : mDisplayContent.mBaseDisplayHeight;
            mService.mPolicy.getStableInsetsLw(rotation, dw, dh, mTmpRect);
            config.setToDefaults();
            config.orientation = (dw <= dh) ? ORIENTATION_PORTRAIT : ORIENTATION_LANDSCAPE;
            config.screenWidthDp = (int)
                    (mService.mPolicy.getConfigDisplayWidth(dw, dh, rotation, baseConfig.uiMode) /
                            mDisplayContent.getDisplayMetrics().density);
            config.screenHeightDp = (int)
                    (mService.mPolicy.getConfigDisplayHeight(dw, dh, rotation, baseConfig.uiMode) /
                            mDisplayContent.getDisplayMetrics().density);
            final Context rotationContext = mService.mContext.createConfigurationContext(config);
            mSnapAlgorithmForRotation[rotation] = new DividerSnapAlgorithm(
                    rotationContext.getResources(), dw, dh, getContentWidth(),
                    config.orientation == ORIENTATION_PORTRAIT, mTmpRect);
        }
    }

    private void loadDimens() {
        final Context context = mService.mContext;
        mDividerWindowWidth = context.getResources().getDimensionPixelSize(
@@ -141,6 +221,7 @@ public class DockedStackDividerController implements DimLayerUser {
                com.android.internal.R.dimen.docked_stack_divider_insets);
        mDividerWindowWidthInactive = WindowManagerService.dipToPixel(
                DIVIDER_WIDTH_INACTIVE_DP, mDisplayContent.getDisplayMetrics());
        initSnapAlgorithmForRotations();
    }

    void onConfigurationChanged() {
+6 −2
Original line number Diff line number Diff line
@@ -1197,16 +1197,20 @@ public class TaskStack implements DimLayer.DimLayerUser,
        }
        mDisplayContent.getLogicalDisplayRect(mTmpRect);
        final int orientation = mService.mCurConfiguration.orientation;
        return getDockSideUnchecked(bounds, mTmpRect, orientation);
    }

    static int getDockSideUnchecked(Rect bounds, Rect displayRect, int orientation) {
        if (orientation == Configuration.ORIENTATION_PORTRAIT) {
            // Portrait mode, docked either at the top or the bottom.
            if (bounds.top - mTmpRect.top <= mTmpRect.bottom - bounds.bottom) {
            if (bounds.top - displayRect.top <= displayRect.bottom - bounds.bottom) {
                return DOCKED_TOP;
            } else {
                return DOCKED_BOTTOM;
            }
        } else if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
            // Landscape mode, docked either on the left or on the right.
            if (bounds.left - mTmpRect.left <= mTmpRect.right - bounds.right) {
            if (bounds.left - displayRect.left <= displayRect.right - bounds.right) {
                return DOCKED_LEFT;
            } else {
                return DOCKED_RIGHT;
Loading