Loading libs/WindowManager/Shell/src/com/android/wm/shell/common/MultiDisplayDragMoveIndicatorController.kt +3 −3 Original line number Diff line number Diff line Loading @@ -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 Loading libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/MultiDisplayVeiledResizeTaskPositioner.kt +31 −13 Original line number Diff line number Diff line Loading @@ -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, Loading Loading @@ -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 ) Loading Loading @@ -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 Loading @@ -222,6 +238,7 @@ class MultiDisplayVeiledResizeTaskPositioner( } t.setAlpha(windowDecoration.taskSurface, alpha) } } t.setFrameTimeline(Choreographer.getInstance().vsyncId) t.apply() } Loading Loading @@ -324,6 +341,7 @@ class MultiDisplayVeiledResizeTaskPositioner( ctrlType = DragPositioningCallback.CTRL_TYPE_UNDEFINED taskBoundsAtDragStart.setEmpty() repositionStartPoint[0f] = 0f hasMovedTaskSurfaceOffScreen = false return Rect(repositionTaskBounds) } Loading libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/MultiDisplayDragMoveIndicatorControllerTest.kt +16 −2 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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) Loading @@ -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, Loading @@ -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 Loading libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/MultiDisplayVeiledResizeTaskPositionerTest.kt +105 −30 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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( Loading @@ -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 { Loading Loading @@ -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) Loading @@ -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, Loading @@ -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() Loading @@ -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( Loading Loading @@ -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 = Loading Loading
libs/WindowManager/Shell/src/com/android/wm/shell/common/MultiDisplayDragMoveIndicatorController.kt +3 −3 Original line number Diff line number Diff line Loading @@ -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 Loading
libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/MultiDisplayVeiledResizeTaskPositioner.kt +31 −13 Original line number Diff line number Diff line Loading @@ -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, Loading Loading @@ -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 ) Loading Loading @@ -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 Loading @@ -222,6 +238,7 @@ class MultiDisplayVeiledResizeTaskPositioner( } t.setAlpha(windowDecoration.taskSurface, alpha) } } t.setFrameTimeline(Choreographer.getInstance().vsyncId) t.apply() } Loading Loading @@ -324,6 +341,7 @@ class MultiDisplayVeiledResizeTaskPositioner( ctrlType = DragPositioningCallback.CTRL_TYPE_UNDEFINED taskBoundsAtDragStart.setEmpty() repositionStartPoint[0f] = 0f hasMovedTaskSurfaceOffScreen = false return Rect(repositionTaskBounds) } Loading
libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/MultiDisplayDragMoveIndicatorControllerTest.kt +16 −2 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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) Loading @@ -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, Loading @@ -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 Loading
libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/MultiDisplayVeiledResizeTaskPositionerTest.kt +105 −30 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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( Loading @@ -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 { Loading Loading @@ -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) Loading @@ -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, Loading @@ -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() Loading @@ -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( Loading Loading @@ -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 = Loading