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

Commit 505d20cb authored by Matt Sziklay's avatar Matt Sziklay Committed by Android (Google) Code Review
Browse files

Merge "Determine indicator type for input outside of display." into main

parents 8f44e78f bd5ccf06
Loading
Loading
Loading
Loading
+22 −28
Original line number Diff line number Diff line
@@ -21,6 +21,12 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;

import static com.android.wm.shell.desktopmode.DesktopModeVisualIndicator.IndicatorType.NO_INDICATOR;
import static com.android.wm.shell.desktopmode.DesktopModeVisualIndicator.IndicatorType.TO_DESKTOP_INDICATOR;
import static com.android.wm.shell.desktopmode.DesktopModeVisualIndicator.IndicatorType.TO_FULLSCREEN_INDICATOR;
import static com.android.wm.shell.desktopmode.DesktopModeVisualIndicator.IndicatorType.TO_SPLIT_LEFT_INDICATOR;
import static com.android.wm.shell.desktopmode.DesktopModeVisualIndicator.IndicatorType.TO_SPLIT_RIGHT_INDICATOR;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.RectEvaluator;
@@ -125,7 +131,7 @@ public class DesktopModeVisualIndicator {
        mContext = context;
        mTaskSurface = taskSurface;
        mRootTdaOrganizer = taskDisplayAreaOrganizer;
        mCurrentType = IndicatorType.NO_INDICATOR;
        mCurrentType = NO_INDICATOR;
        mDragStartState = dragStartState;
    }

@@ -136,8 +142,16 @@ public class DesktopModeVisualIndicator {
    @NonNull
    IndicatorType updateIndicatorType(PointF inputCoordinates) {
        final DisplayLayout layout = mDisplayController.getDisplayLayout(mTaskInfo.displayId);
        // Perform a quick check first: any input off the left edge of the display should be split
        // left, and split right for the right edge. This is universal across all drag event types.
        if (inputCoordinates.x < 0) return TO_SPLIT_LEFT_INDICATOR;
        if (inputCoordinates.x > layout.width()) return TO_SPLIT_RIGHT_INDICATOR;
        // If we are in freeform, we don't want a visible indicator in the "freeform" drag zone.
        IndicatorType result = IndicatorType.NO_INDICATOR;
        // In drags not originating on a freeform caption, we should default to a TO_DESKTOP
        // indicator.
        IndicatorType result = mDragStartState == DragStartState.FROM_FREEFORM
                ? NO_INDICATOR
                : TO_DESKTOP_INDICATOR;
        final int transitionAreaWidth = mContext.getResources().getDimensionPixelSize(
                com.android.wm.shell.R.dimen.desktop_mode_transition_region_thickness);
        // Because drags in freeform use task position for indicator calculation, we need to
@@ -149,10 +163,8 @@ public class DesktopModeVisualIndicator {
                captionHeight);
        final Region splitRightRegion = calculateSplitRightRegion(layout, transitionAreaWidth,
                captionHeight);
        final Region toDesktopRegion = calculateToDesktopRegion(layout, splitLeftRegion,
                splitRightRegion, fullscreenRegion);
        if (fullscreenRegion.contains((int) inputCoordinates.x, (int) inputCoordinates.y)) {
            result = IndicatorType.TO_FULLSCREEN_INDICATOR;
            result = TO_FULLSCREEN_INDICATOR;
        }
        if (splitLeftRegion.contains((int) inputCoordinates.x, (int) inputCoordinates.y)) {
            result = IndicatorType.TO_SPLIT_LEFT_INDICATOR;
@@ -160,9 +172,6 @@ public class DesktopModeVisualIndicator {
        if (splitRightRegion.contains((int) inputCoordinates.x, (int) inputCoordinates.y)) {
            result = IndicatorType.TO_SPLIT_RIGHT_INDICATOR;
        }
        if (toDesktopRegion.contains((int) inputCoordinates.x, (int) inputCoordinates.y)) {
            result = IndicatorType.TO_DESKTOP_INDICATOR;
        }
        if (mDragStartState != DragStartState.DRAGGED_INTENT) {
            transitionIndicator(result);
        }
@@ -182,7 +191,7 @@ public class DesktopModeVisualIndicator {
                    R.dimen.desktop_mode_fullscreen_region_scale);
            final float toFullscreenWidth = (layout.width() * toFullscreenScale);
            region.union(new Rect((int) ((layout.width() / 2f) - (toFullscreenWidth / 2f)),
                    -captionHeight,
                    Short.MIN_VALUE,
                    (int) ((layout.width() / 2f) + (toFullscreenWidth / 2f)),
                    transitionHeight));
        }
@@ -192,28 +201,13 @@ public class DesktopModeVisualIndicator {
                || mDragStartState == DragStartState.DRAGGED_INTENT
        ) {
            region.union(new Rect(0,
                    -captionHeight,
                    Short.MIN_VALUE,
                    layout.width(),
                    transitionHeight));
        }
        return region;
    }

    @VisibleForTesting
    Region calculateToDesktopRegion(DisplayLayout layout,
            Region splitLeftRegion, Region splitRightRegion,
            Region toFullscreenRegion) {
        final Region region = new Region();
        // If in desktop, we need no region. Otherwise it's the same for all windowing modes.
        if (mDragStartState != DragStartState.FROM_FREEFORM) {
            region.union(new Rect(0, 0, layout.width(), layout.height()));
            region.op(splitLeftRegion, Region.Op.DIFFERENCE);
            region.op(splitRightRegion, Region.Op.DIFFERENCE);
            region.op(toFullscreenRegion, Region.Op.DIFFERENCE);
        }
        return region;
    }

    @VisibleForTesting
    Region calculateSplitLeftRegion(DisplayLayout layout,
            int transitionEdgeWidth, int captionHeight) {
@@ -311,7 +305,7 @@ public class DesktopModeVisualIndicator {
                }
            });
        }
        mCurrentType = IndicatorType.NO_INDICATOR;
        mCurrentType = NO_INDICATOR;
    }

    /**
@@ -322,9 +316,9 @@ public class DesktopModeVisualIndicator {
        if (mView == null) {
            createView();
        }
        if (mCurrentType == IndicatorType.NO_INDICATOR) {
        if (mCurrentType == NO_INDICATOR) {
            fadeInIndicator(newType);
        } else if (newType == IndicatorType.NO_INDICATOR) {
        } else if (newType == NO_INDICATOR) {
            fadeOutIndicator(null /* finishCallback */);
        } else {
            final VisualIndicatorAnimator animator = VisualIndicatorAnimator.animateIndicatorType(
+1 −1
Original line number Diff line number Diff line
@@ -1594,7 +1594,7 @@ class DesktopTasksController(
            return
        }

        val indicator = visualIndicator ?: return
        val indicator = getVisualIndicator() ?: return
        val indicatorType =
            indicator.updateIndicatorType(
                PointF(inputCoordinate.x, currentDragBounds.top.toFloat()),
+22 −20
Original line number Diff line number Diff line
@@ -17,8 +17,8 @@
package com.android.wm.shell.desktopmode

import android.app.ActivityManager.RunningTaskInfo
import android.graphics.PointF
import android.graphics.Rect
import android.graphics.Region
import android.testing.AndroidTestingRunner
import android.view.SurfaceControl
import androidx.test.filters.SmallTest
@@ -33,6 +33,7 @@ import com.google.common.truth.Truth.assertThat
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.ArgumentMatchers.anyInt
import org.mockito.Mock
import org.mockito.kotlin.whenever

@@ -58,13 +59,15 @@ class DesktopModeVisualIndicatorTest : ShellTestCase() {
        whenever(displayLayout.width()).thenReturn(DISPLAY_BOUNDS.width())
        whenever(displayLayout.height()).thenReturn(DISPLAY_BOUNDS.height())
        whenever(displayLayout.stableInsets()).thenReturn(STABLE_INSETS)
        whenever(displayController.getDisplayLayout(anyInt())).thenReturn(displayLayout)
    }

    @Test
    fun testFullscreenRegionCalculation() {
        createVisualIndicator(DesktopModeVisualIndicator.DragStartState.FROM_FULLSCREEN)
        var testRegion = visualIndicator.calculateFullscreenRegion(displayLayout, CAPTION_HEIGHT)
        assertThat(testRegion.bounds).isEqualTo(Rect(0, -50, 2400, 2 * STABLE_INSETS.top))
        assertThat(testRegion.bounds).isEqualTo(Rect(0, Short.MIN_VALUE.toInt(), 2400,
            2 * STABLE_INSETS.top))

        createVisualIndicator(DesktopModeVisualIndicator.DragStartState.FROM_FREEFORM)
        testRegion = visualIndicator.calculateFullscreenRegion(displayLayout, CAPTION_HEIGHT)
@@ -75,17 +78,19 @@ class DesktopModeVisualIndicatorTest : ShellTestCase() {
        val toFullscreenWidth = displayLayout.width() * toFullscreenScale
        assertThat(testRegion.bounds).isEqualTo(Rect(
            (DISPLAY_BOUNDS.width() / 2f - toFullscreenWidth / 2f).toInt(),
            -50,
            Short.MIN_VALUE.toInt(),
            (DISPLAY_BOUNDS.width() / 2f + toFullscreenWidth / 2f).toInt(),
            transitionHeight))

        createVisualIndicator(DesktopModeVisualIndicator.DragStartState.FROM_SPLIT)
        testRegion = visualIndicator.calculateFullscreenRegion(displayLayout, CAPTION_HEIGHT)
        assertThat(testRegion.bounds).isEqualTo(Rect(0, -50, 2400, 2 * STABLE_INSETS.top))
        assertThat(testRegion.bounds).isEqualTo(Rect(0, Short.MIN_VALUE.toInt(), 2400,
            2 * STABLE_INSETS.top))

        createVisualIndicator(DesktopModeVisualIndicator.DragStartState.DRAGGED_INTENT)
        testRegion = visualIndicator.calculateFullscreenRegion(displayLayout, CAPTION_HEIGHT)
        assertThat(testRegion.bounds).isEqualTo(Rect(0, -50, 2400, transitionHeight))
        assertThat(testRegion.bounds).isEqualTo(Rect(0, Short.MIN_VALUE.toInt(), 2400,
            transitionHeight))
    }

    @Test
@@ -133,22 +138,19 @@ class DesktopModeVisualIndicatorTest : ShellTestCase() {
    }

    @Test
    fun testToDesktopRegionCalculation() {
    fun testDefaultIndicators() {
        createVisualIndicator(DesktopModeVisualIndicator.DragStartState.FROM_FULLSCREEN)
        val fullscreenRegion = visualIndicator.calculateFullscreenRegion(displayLayout,
            CAPTION_HEIGHT)
        val splitLeftRegion = visualIndicator.calculateSplitLeftRegion(displayLayout,
            TRANSITION_AREA_WIDTH, CAPTION_HEIGHT)
        val splitRightRegion = visualIndicator.calculateSplitRightRegion(displayLayout,
            TRANSITION_AREA_WIDTH, CAPTION_HEIGHT)
        val desktopRegion = visualIndicator.calculateToDesktopRegion(displayLayout,
            splitLeftRegion, splitRightRegion, fullscreenRegion)
        var testRegion = Region()
        testRegion.union(DISPLAY_BOUNDS)
        testRegion.op(splitLeftRegion, Region.Op.DIFFERENCE)
        testRegion.op(splitRightRegion, Region.Op.DIFFERENCE)
        testRegion.op(fullscreenRegion, Region.Op.DIFFERENCE)
        assertThat(desktopRegion).isEqualTo(testRegion)
        var result = visualIndicator.updateIndicatorType(PointF(-10000f, 500f))
        assertThat(result).isEqualTo(DesktopModeVisualIndicator.IndicatorType.TO_SPLIT_LEFT_INDICATOR)
        createVisualIndicator(DesktopModeVisualIndicator.DragStartState.FROM_SPLIT)
        result = visualIndicator.updateIndicatorType(PointF(10000f, 500f))
        assertThat(result).isEqualTo(DesktopModeVisualIndicator.IndicatorType.TO_SPLIT_RIGHT_INDICATOR)
        createVisualIndicator(DesktopModeVisualIndicator.DragStartState.DRAGGED_INTENT)
        result = visualIndicator.updateIndicatorType(PointF(500f, 10000f))
        assertThat(result).isEqualTo(DesktopModeVisualIndicator.IndicatorType.TO_DESKTOP_INDICATOR)
        createVisualIndicator(DesktopModeVisualIndicator.DragStartState.FROM_FREEFORM)
        result = visualIndicator.updateIndicatorType(PointF(500f, 10000f))
        assertThat(result).isEqualTo(DesktopModeVisualIndicator.IndicatorType.NO_INDICATOR)
    }

    private fun createVisualIndicator(dragStartState: DesktopModeVisualIndicator.DragStartState) {
+6 −2
Original line number Diff line number Diff line
@@ -2643,13 +2643,17 @@ class DesktopTasksControllerTest : ShellTestCase() {
  @Test
  fun onDesktopDragMove_endsOutsideValidDragArea_snapsToValidBounds() {
    val task = setUpFreeformTask()
    val spyController = spy(controller)
    val mockSurface = mock(SurfaceControl::class.java)
    val mockDisplayLayout = mock(DisplayLayout::class.java)
    whenever(displayController.getDisplayLayout(task.displayId)).thenReturn(mockDisplayLayout)
    whenever(mockDisplayLayout.stableInsets()).thenReturn(Rect(0, 100, 2000, 2000))
    controller.onDragPositioningMove(task, mockSurface, 200f, Rect(100, -100, 500, 1000))
    spyController.onDragPositioningMove(task, mockSurface, 200f, Rect(100, -100, 500, 1000))

    controller.onDragPositioningEnd(
    whenever(spyController.getVisualIndicator()).thenReturn(desktopModeVisualIndicator)
    whenever(desktopModeVisualIndicator.updateIndicatorType(anyOrNull()))
      .thenReturn(DesktopModeVisualIndicator.IndicatorType.NO_INDICATOR)
    spyController.onDragPositioningEnd(
        task,
        mockSurface,
        Point(100, -100), /* position */