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

Commit 0912c28a authored by Riley Jones's avatar Riley Jones
Browse files

Handling DisplayCutouts more granularly to allow the FAB to occupy more space

Flag: com.android.systemui.floating_menu_display_cutout_support
Bug: 384399408
Test: atest com.android.systemup.floatingmenu

Change-Id: I37095dffc48cb653a44d8be1986667f7c282844e
parent e64e000f
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -37,6 +37,16 @@ flag {
    bug: "297556899"
}

flag {
    name: "floating_menu_display_cutout_support"
    namespace: "accessibility"
    description: "Makes FAB properly react to and avoid DisplayCutouts."
    bug: "384399408"
    metadata {
      purpose: PURPOSE_BUGFIX
    }
}

flag {
    name: "floating_menu_drag_to_hide"
    namespace: "accessibility"
+2 −1
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@ import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;

import android.graphics.PointF;
import android.platform.test.annotations.DisableFlags;
import android.platform.test.annotations.EnableFlags;
import android.testing.TestableLooper;
@@ -210,7 +211,7 @@ public class MenuListViewTouchHandlerTest extends SysuiTestCase {
        mTouchHandler.onInterceptTouchEvent(mStubListView, stubMoveEvent);
        mTouchHandler.onInterceptTouchEvent(mStubListView, stubUpEvent);

        verify(mMenuAnimationController).flingMenuThenSpringToEdge(anyFloat(), anyFloat(),
        verify(mMenuAnimationController).flingMenuThenSpringToEdge(any(PointF.class), anyFloat(),
                anyFloat());
    }

+25 −8
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ import android.graphics.Rect;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import android.view.DisplayCutout;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.OvershootInterpolator;
@@ -197,7 +198,7 @@ class MenuAnimationController {
        constrainPositionAndUpdate(position, /* writeToPosition = */ true);
    }

    void flingMenuThenSpringToEdge(float x, float velocityX, float velocityY) {
    void flingMenuThenSpringToEdge(PointF position, float velocityX, float velocityY) {
        final boolean shouldMenuFlingLeft = isOnLeftSide()
                ? velocityX < ESCAPE_VELOCITY
                : velocityX < -ESCAPE_VELOCITY;
@@ -205,9 +206,17 @@ class MenuAnimationController {
        final Rect draggableBounds = mMenuView.getMenuDraggableBounds();
        final float finalPositionX = shouldMenuFlingLeft
                ? draggableBounds.left : draggableBounds.right;

        final DisplayCutout displayCutout = mMenuViewAppearance.getDisplayCutout();
        final float finalPositionY =
                (displayCutout == null) ? position.y
                        : mMenuViewAppearance.avoidVerticalDisplayCutout(
                                position.y, draggableBounds,
                                shouldMenuFlingLeft
                                        ? displayCutout.getBoundingRectLeft()
                                        : displayCutout.getBoundingRectRight()
                        );
        final float minimumVelocityToReachEdge =
                (finalPositionX - x) * (FLING_FRICTION_SCALAR * DEFAULT_FRICTION);
                (finalPositionX - position.x) * (FLING_FRICTION_SCALAR * DEFAULT_FRICTION);

        final float startXVelocity = shouldMenuFlingLeft
                ? Math.min(minimumVelocityToReachEdge, velocityX)
@@ -219,12 +228,20 @@ class MenuAnimationController {
                createSpringForce(),
                finalPositionX);

        if (com.android.systemui.Flags.floatingMenuDisplayCutoutSupport()) {
            flingThenSpringMenuWith(DynamicAnimation.TRANSLATION_Y,
                    velocityY,
                    FLING_FRICTION_SCALAR,
                    createSpringForce(),
                    (finalPositionY != position.y) ? finalPositionY : null);
        } else {
            flingThenSpringMenuWith(DynamicAnimation.TRANSLATION_Y,
                    velocityY,
                    FLING_FRICTION_SCALAR,
                    createSpringForce(),
                    /* finalPosition= */ null);
        }
    }

    private void flingThenSpringMenuWith(DynamicAnimation.ViewProperty property, float velocity,
            float friction, SpringForce spring, Float finalPosition) {
+2 −1
Original line number Diff line number Diff line
@@ -105,7 +105,8 @@ class MenuListViewTouchHandler implements RecyclerView.OnItemTouchListener {
                    if (mDragToInteractAnimationController.maybeConsumeUpMotionEvent(motionEvent)
                            == empty) {
                        mVelocityTracker.computeCurrentVelocity(VELOCITY_UNIT_SECONDS);
                        mMenuAnimationController.flingMenuThenSpringToEdge(endX,
                        mMenuAnimationController.flingMenuThenSpringToEdge(
                                new PointF(endX, mMenuTranslationDown.y + dy),
                                mVelocityTracker.getXVelocity(), mVelocityTracker.getYVelocity());
                        mMenuAnimationController.fadeOutIfEnabled();
                    }
+34 −1
Original line number Diff line number Diff line
@@ -28,12 +28,14 @@ import android.graphics.Insets;
import android.graphics.PointF;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.view.DisplayCutout;
import android.view.WindowInsets;
import android.view.WindowManager;
import android.view.WindowMetrics;

import androidx.annotation.DimenRes;

import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.res.R;

import java.lang.annotation.Retention;
@@ -291,7 +293,7 @@ class MenuViewAppearance {
        final WindowMetrics windowMetrics = mWindowManager.getCurrentWindowMetrics();
        final WindowInsets windowInsets = windowMetrics.getWindowInsets();
        final Insets insets = windowInsets.getInsetsIgnoringVisibility(
                WindowInsets.Type.systemBars() | WindowInsets.Type.displayCutout());
                WindowInsets.Type.systemBars());

        final Rect bounds = new Rect(windowMetrics.getBounds());
        bounds.left += insets.left;
@@ -302,6 +304,37 @@ class MenuViewAppearance {
        return bounds;
    }

    DisplayCutout getDisplayCutout() {
        return mWindowManager.getCurrentWindowMetrics().getWindowInsets().getDisplayCutout();
    }

    float avoidVerticalDisplayCutout(float y, Rect bounds, Rect cutout) {
        int menuHeight = calculateActualMenuHeight();
        return avoidVerticalDisplayCutout(y, menuHeight, bounds, cutout);
    }

    @VisibleForTesting
    public static float avoidVerticalDisplayCutout(
            float y, float menuHeight, Rect bounds, Rect cutout) {
        if (cutout.top > y + menuHeight || cutout.bottom < y) {
            return y;
        }

        boolean topAvailable = cutout.top - bounds.top >= menuHeight;
        boolean bottomAvailable = bounds.bottom - cutout.bottom >= menuHeight;
        boolean topOrBottom;
        if (!topAvailable && !bottomAvailable) {
            return y;
        } else if (topAvailable && !bottomAvailable) {
            topOrBottom = true;
        } else if (!topAvailable && bottomAvailable) {
            topOrBottom = false;
        } else {
            topOrBottom = y + menuHeight * 0.5f < cutout.centerY();
        }
        return (topOrBottom) ? cutout.top - menuHeight : cutout.bottom;
    }

    boolean isMenuOnLeftSide() {
        return mPercentagePosition.getPercentageX() < 0.5f;
    }
Loading