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

Commit 6ec233a4 authored by Qijing Yao's avatar Qijing Yao Committed by Android (Google) Code Review
Browse files

Merge "Reapply "Correct opacitiy for drag move indicator"" into main

parents 53a68cdb e25df5e0
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -56,11 +56,11 @@ class MultiDisplayDragMoveIndicatorController(
        val transaction = transactionSupplier()
        for (displayId in displayIds) {
            if (
                displayId == startDisplayId ||
                (displayId == startDisplayId &&
                    !DesktopExperienceFlags.ENABLE_WINDOW_DROP_SMOOTH_TRANSITION.isTrue) ||
                    !desktopState.isDesktopModeSupportedOnDisplay(displayId)
            ) {
                // No need to render indicators on the original display where the drag started,
                // or on displays that do not support desktop mode.
                // No need to render indicators on displays that do not support desktop mode.
                continue
            }
            val displayLayout = displayController.getDisplayLayout(displayId) ?: continue
+31 −13
Original line number Diff line number Diff line
@@ -80,6 +80,7 @@ class MultiDisplayVeiledResizeTaskPositioner(
    private var startDisplayId = 0
    private var hasMoved = false
    private val displayIds = mutableSetOf<Int>()
    private var hasMovedTaskSurfaceOffScreen = false

    constructor(
        taskOrganizer: ShellTaskOrganizer,
@@ -111,6 +112,7 @@ class MultiDisplayVeiledResizeTaskPositioner(
    override fun onDragPositioningStart(ctrlType: Int, displayId: Int, x: Float, y: Float): Rect {
        this.ctrlType = ctrlType
        startDisplayId = displayId
        hasMovedTaskSurfaceOffScreen = false
        taskBoundsAtDragStart.set(
            windowDecoration.taskInfo.configuration.windowConfiguration.bounds
        )
@@ -207,13 +209,27 @@ class MultiDisplayVeiledResizeTaskPositioner(
                    displayIds,
                    transactionSupplier,
                )

                if (DesktopExperienceFlags.ENABLE_WINDOW_DROP_SMOOTH_TRANSITION.isTrue) {
                    // Move the original task surface off-screen to hide it. A mirrored surface is
                    // used for the drag indicator on all displays, including the start display.
                    // This is necessary for independent opacity control, as a mirror's alpha is
                    // capped by its source.
                    if (!hasMovedTaskSurfaceOffScreen) {
                        hasMovedTaskSurfaceOffScreen = true
                        t.setPosition(
                            windowDecoration.taskSurface,
                            startDisplayLayout.width().toFloat(),
                            startDisplayLayout.height().toFloat(),
                        )
                    }
                } else {
                    t.setPosition(
                        windowDecoration.taskSurface,
                        repositionTaskBounds.left.toFloat(),
                        repositionTaskBounds.top.toFloat(),
                    )
                // Make the window translucent in the case when the cursor moves to another display.
                    // Make the window translucent in the case when the cursor moves to another
                    // display.
                    val alpha =
                        if (startDisplayId == displayId) {
                            ALPHA_FOR_WINDOW_ON_DISPLAY_WITH_CURSOR
@@ -222,6 +238,7 @@ class MultiDisplayVeiledResizeTaskPositioner(
                        }
                    t.setAlpha(windowDecoration.taskSurface, alpha)
                }
            }
            t.setFrameTimeline(Choreographer.getInstance().vsyncId)
            t.apply()
        }
@@ -324,6 +341,7 @@ class MultiDisplayVeiledResizeTaskPositioner(
        ctrlType = DragPositioningCallback.CTRL_TYPE_UNDEFINED
        taskBoundsAtDragStart.setEmpty()
        repositionStartPoint[0f] = 0f
        hasMovedTaskSurfaceOffScreen = false
        return Rect(repositionTaskBounds)
    }

+16 −2
Original line number Diff line number Diff line
@@ -19,10 +19,12 @@ import android.app.ActivityManager.RunningTaskInfo
import android.content.res.Configuration
import android.graphics.Rect
import android.graphics.RectF
import android.platform.test.annotations.EnableFlags
import android.testing.TestableResources
import android.view.SurfaceControl
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.window.flags.Flags
import com.android.wm.shell.RootTaskDisplayAreaOrganizer
import com.android.wm.shell.ShellTestCase
import com.android.wm.shell.common.MultiDisplayTestUtil.TestDisplay
@@ -85,6 +87,7 @@ class MultiDisplayDragMoveIndicatorControllerTest : ShellTestCase() {
        taskInfo.taskId = TASK_ID
        whenever(displayController.getDisplayLayout(0)).thenReturn(spyDisplayLayout0)
        whenever(displayController.getDisplayLayout(1)).thenReturn(spyDisplayLayout1)
        whenever(displayController.getDisplayContext(0)).thenReturn(mContext)
        whenever(displayController.getDisplayContext(1)).thenReturn(mContext)
        whenever(indicatorSurfaceFactory.create(eq(mContext), eq(taskLeash)))
            .thenReturn(indicatorSurface)
@@ -109,7 +112,8 @@ class MultiDisplayDragMoveIndicatorControllerTest : ShellTestCase() {
    }

    @Test
    fun onDrag_boundsIntersectWithStartDisplay_noIndicator() {
    @EnableFlags(Flags.FLAG_ENABLE_WINDOW_DROP_SMOOTH_TRANSITION)
    fun onDrag_boundsIntersectWithStartDisplay_showIndicator() {
        controller.onDragMove(
            RectF(100f, 100f, 200f, 200f), // intersect with display 0
            currentDisplayId = 0,
@@ -121,7 +125,17 @@ class MultiDisplayDragMoveIndicatorControllerTest : ShellTestCase() {
            transaction
        }

        verify(indicatorSurfaceFactory, never()).create(any(), any())
        verify(indicatorSurfaceFactory, times(1)).create(eq(mContext), eq(taskLeash))
        verify(indicatorSurface, times(1))
            .show(
                transaction,
                taskInfo,
                rootTaskDisplayAreaOrganizer,
                0,
                Rect(100, 100, 200, 200),
                MultiDisplayDragMoveIndicatorSurface.Visibility.VISIBLE,
                1.0f,
            )
    }

    @Test
+105 −30
Original line number Diff line number Diff line
@@ -60,9 +60,9 @@ import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.kotlin.any
import org.mockito.kotlin.argThat
import org.mockito.kotlin.argumentCaptor
import org.mockito.kotlin.doAnswer
import org.mockito.kotlin.eq
import org.mockito.kotlin.inOrder
import org.mockito.kotlin.mock
import org.mockito.kotlin.never
import org.mockito.kotlin.times
@@ -225,10 +225,6 @@ class MultiDisplayVeiledResizeTaskPositionerTest : ShellTestCase() {
            STARTING_BOUNDS.left.toFloat() + 60,
            STARTING_BOUNDS.top.toFloat() + 100,
        )
        val rectAfterMove = Rect(STARTING_BOUNDS)
        rectAfterMove.offset(60, 100)
        verify(mockTransaction)
            .setPosition(any(), eq(rectAfterMove.left.toFloat()), eq(rectAfterMove.top.toFloat()))

        val endBounds =
            taskPositioner.onDragPositioningEnd(
@@ -245,6 +241,41 @@ class MultiDisplayVeiledResizeTaskPositionerTest : ShellTestCase() {
        Assert.assertEquals(rectAfterEnd, endBounds)
    }

    @Test
    @EnableFlags(Flags.FLAG_ENABLE_WINDOW_DROP_SMOOTH_TRANSITION)
    fun testDragResize_movesTask_movesTaskSurfaceOffscreen() = runOnUiThread {
        whenever(spyDisplayLayout0.width()).thenReturn(DISPLAY_BOUNDS.width())
        whenever(spyDisplayLayout0.height()).thenReturn(DISPLAY_BOUNDS.height())

        taskPositioner.onDragPositioningStart(
            CTRL_TYPE_UNDEFINED,
            DISPLAY_ID_0,
            STARTING_BOUNDS.left.toFloat(),
            STARTING_BOUNDS.top.toFloat(),
        )

        taskPositioner.onDragPositioningMove(
            DISPLAY_ID_0,
            STARTING_BOUNDS.left.toFloat() + 60,
            STARTING_BOUNDS.top.toFloat() + 100,
        )

        val leftAfterMoveCaptor = argumentCaptor<Float>()
        val topAfterMoveCaptor = argumentCaptor<Float>()
        verify(mockTransaction)
            .setPosition(
                eq(mockSurfaceControl),
                leftAfterMoveCaptor.capture(),
                topAfterMoveCaptor.capture(),
            )
        val rectAfterMove = Rect(STARTING_BOUNDS)
        rectAfterMove.offsetTo(
            leftAfterMoveCaptor.firstValue.toInt(),
            topAfterMoveCaptor.firstValue.toInt(),
        )
        Assert.assertFalse(DISPLAY_BOUNDS.intersect(rectAfterMove))
    }

    @Test
    @EnableFlags(Flags.FLAG_ENABLE_WINDOW_DROP_SMOOTH_TRANSITION)
    fun testDragResize_movesTaskOnSameDisplay_noPxDpConversion() = runOnUiThread {
@@ -278,12 +309,6 @@ class MultiDisplayVeiledResizeTaskPositionerTest : ShellTestCase() {

        taskPositioner.onDragPositioningMove(DISPLAY_ID_1, 200f, 1900f)

        val rectAfterMove = Rect(200, -50, 300, 50)
        verify(mockTransaction)
            .setPosition(any(), eq(rectAfterMove.left.toFloat()), eq(rectAfterMove.top.toFloat()))
        verify(mockTransaction)
            .setAlpha(eq(mockWindowDecoration.taskSurface), eq(ALPHA_FOR_TRANSLUCENT_WINDOW))

        val endBounds = taskPositioner.onDragPositioningEnd(DISPLAY_ID_1, 300f, 450f)
        val rectAfterEnd = Rect(300, 450, 500, 650)

@@ -295,7 +320,10 @@ class MultiDisplayVeiledResizeTaskPositionerTest : ShellTestCase() {

    @Test
    @EnableFlags(Flags.FLAG_ENABLE_WINDOW_DROP_SMOOTH_TRANSITION)
    fun testDragResize_movesTaskToNewDisplayThenBackToOriginalDisplay() = runOnUiThread {
    fun testDragResize_movesTaskToNewDisplay_movesTaskSurfaceOffscreen() = runOnUiThread {
        whenever(spyDisplayLayout0.width()).thenReturn(DISPLAY_BOUNDS.width())
        whenever(spyDisplayLayout0.height()).thenReturn(DISPLAY_BOUNDS.height())

        taskPositioner.onDragPositioningStart(
            CTRL_TYPE_UNDEFINED,
            DISPLAY_ID_0,
@@ -303,31 +331,43 @@ class MultiDisplayVeiledResizeTaskPositionerTest : ShellTestCase() {
            STARTING_BOUNDS.top.toFloat(),
        )

        val inOrder = inOrder(mockTransaction)
        taskPositioner.onDragPositioningMove(DISPLAY_ID_1, 200f, 1900f)

        val leftAfterMoveCaptor = argumentCaptor<Float>()
        val topAfterMoveCaptor = argumentCaptor<Float>()
        verify(mockTransaction)
            .setPosition(
                eq(mockSurfaceControl),
                leftAfterMoveCaptor.capture(),
                topAfterMoveCaptor.capture(),
            )
        val rectAfterMove = Rect(STARTING_BOUNDS)
        rectAfterMove.offsetTo(
            leftAfterMoveCaptor.firstValue.toInt(),
            topAfterMoveCaptor.firstValue.toInt(),
        )
        Assert.assertFalse(DISPLAY_BOUNDS.intersect(rectAfterMove))
    }

    @Test
    @EnableFlags(Flags.FLAG_ENABLE_WINDOW_DROP_SMOOTH_TRANSITION)
    fun testDragResize_movesTaskToNewDisplayThenBackToOriginalDisplay() = runOnUiThread {
        taskPositioner.onDragPositioningStart(
            CTRL_TYPE_UNDEFINED,
            DISPLAY_ID_0,
            STARTING_BOUNDS.left.toFloat(),
            STARTING_BOUNDS.top.toFloat(),
        )

        // Move to the display 1
        taskPositioner.onDragPositioningMove(DISPLAY_ID_1, 200f, 800f)
        val rectAfterMove = Rect(200, -600, 300, -400)
        inOrder
            .verify(mockTransaction)
            .setPosition(any(), eq(rectAfterMove.left.toFloat()), eq(rectAfterMove.top.toFloat()))
        inOrder
            .verify(mockTransaction)
            .setAlpha(eq(mockWindowDecoration.taskSurface), eq(ALPHA_FOR_TRANSLUCENT_WINDOW))

        // Moving back to the original display
        taskPositioner.onDragPositioningMove(DISPLAY_ID_0, 100f, 1500f)
        rectAfterMove.set(100, 1500, 200, 1700)
        inOrder
            .verify(mockTransaction)
            .setPosition(any(), eq(rectAfterMove.left.toFloat()), eq(rectAfterMove.top.toFloat()))
        inOrder
            .verify(mockTransaction)
            .setAlpha(eq(mockWindowDecoration.taskSurface), eq(ALPHA_FOR_VISIBLE_WINDOW))

        // Finish the drag move on the original display
        val endBounds = taskPositioner.onDragPositioningEnd(DISPLAY_ID_0, 50f, 50f)
        rectAfterMove.set(50, 50, 150, 150)
        val rectAfterMove = Rect(50, 50, 150, 150)

        verify(mockWindowDecoration, never()).showResizeVeil(any())
        verify(mockWindowDecoration, never()).hideResizeVeil()
@@ -335,6 +375,43 @@ class MultiDisplayVeiledResizeTaskPositionerTest : ShellTestCase() {
        Assert.assertEquals(rectAfterMove, endBounds)
    }

    @Test
    @EnableFlags(Flags.FLAG_ENABLE_WINDOW_DROP_SMOOTH_TRANSITION)
    fun testDragResize_movesTaskToNewDisplayThenBackToOriginalDisplay_movesTaskSurfaceOffscreen() =
        runOnUiThread {
            whenever(spyDisplayLayout0.width()).thenReturn(DISPLAY_BOUNDS.width())
            whenever(spyDisplayLayout0.height()).thenReturn(DISPLAY_BOUNDS.height())

            taskPositioner.onDragPositioningStart(
                CTRL_TYPE_UNDEFINED,
                DISPLAY_ID_0,
                STARTING_BOUNDS.left.toFloat(),
                STARTING_BOUNDS.top.toFloat(),
            )

            // Move to the display 1
            taskPositioner.onDragPositioningMove(DISPLAY_ID_1, 200f, 800f)

            // Moving back to the original display
            taskPositioner.onDragPositioningMove(DISPLAY_ID_0, 100f, 1500f)

            // Check that setPosition is only called once and the surface is outside of display.
            val leftAfterMoveCaptor = argumentCaptor<Float>()
            val topAfterMoveCaptor = argumentCaptor<Float>()
            verify(mockTransaction)
                .setPosition(
                    eq(mockSurfaceControl),
                    leftAfterMoveCaptor.capture(),
                    topAfterMoveCaptor.capture(),
                )
            val rectAfterMove = Rect(STARTING_BOUNDS)
            rectAfterMove.offsetTo(
                leftAfterMoveCaptor.firstValue.toInt(),
                topAfterMoveCaptor.firstValue.toInt(),
            )
            Assert.assertFalse(DISPLAY_BOUNDS.intersect(rectAfterMove))
        }

    @Test
    fun testDragResize_resize_boundsUpdateOnEnd() = runOnUiThread {
        taskPositioner.onDragPositioningStart(
@@ -796,8 +873,6 @@ class MultiDisplayVeiledResizeTaskPositionerTest : ShellTestCase() {
        private const val NAVBAR_HEIGHT = 50
        private const val CAPTION_HEIGHT = 50
        private const val DISALLOWED_AREA_FOR_END_BOUNDS_HEIGHT = 10
        private const val ALPHA_FOR_TRANSLUCENT_WINDOW = 0.7f
        private const val ALPHA_FOR_VISIBLE_WINDOW = 1.0f
        private val DISPLAY_BOUNDS = Rect(0, 0, 2400, 1600)
        private val STARTING_BOUNDS = Rect(100, 100, 200, 200)
        private val STABLE_BOUNDS_LANDSCAPE =