diff options
7 files changed, 110 insertions, 64 deletions
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/ToggleResizeDesktopTaskTransitionHandler.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/ToggleResizeDesktopTaskTransitionHandler.kt index 5e84019b14f5..1a66ca808dad 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/ToggleResizeDesktopTaskTransitionHandler.kt +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/ToggleResizeDesktopTaskTransitionHandler.kt @@ -47,6 +47,7 @@ class ToggleResizeDesktopTaskTransitionHandler( private var boundsAnimator: Animator? = null private var initialBounds: Rect? = null + private var callback: (() -> Unit)? = null constructor( transitions: Transitions, @@ -61,9 +62,14 @@ class ToggleResizeDesktopTaskTransitionHandler( * bounds of the actual task). This is provided so that the animation resizing can begin where * the task leash currently is for smoother UX. */ - fun startTransition(wct: WindowContainerTransaction, taskLeashBounds: Rect? = null) { + fun startTransition( + wct: WindowContainerTransaction, + taskLeashBounds: Rect? = null, + callback: (() -> Unit)? = null, + ) { transitions.startTransition(TRANSIT_DESKTOP_MODE_TOGGLE_RESIZE, wct, this) initialBounds = taskLeashBounds + this.callback = callback } fun setOnTaskResizeAnimationListener(listener: OnTaskResizeAnimationListener) { @@ -121,6 +127,8 @@ class ToggleResizeDesktopTaskTransitionHandler( interactionJankMonitor.end(Cuj.CUJ_DESKTOP_MODE_MAXIMIZE_WINDOW) interactionJankMonitor.end(Cuj.CUJ_DESKTOP_MODE_UNMAXIMIZE_WINDOW) interactionJankMonitor.end(Cuj.CUJ_DESKTOP_MODE_SNAP_RESIZE) + callback?.invoke() + callback = null }, ) addUpdateListener { anim -> diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/tiling/DesktopTilingDividerWindowManager.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/tiling/DesktopTilingDividerWindowManager.kt index cb45c1732476..57f8046065b4 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/tiling/DesktopTilingDividerWindowManager.kt +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/tiling/DesktopTilingDividerWindowManager.kt @@ -16,6 +16,9 @@ package com.android.wm.shell.windowdecor.tiling +import android.animation.Animator +import android.animation.AnimatorListenerAdapter +import android.animation.ValueAnimator import android.content.Context import android.content.res.Configuration import android.graphics.Path @@ -144,7 +147,6 @@ class DesktopTilingDividerWindowManager( * @param relativeLeash the task leash that the TilingDividerView should be shown on top of. */ fun generateViewHost(relativeLeash: SurfaceControl) { - val t = transactionSupplier.get() val surfaceControlViewHost = SurfaceControlViewHost(context, context.display, this, "DesktopTilingManager") val dividerView = @@ -155,22 +157,40 @@ class DesktopTilingDividerWindowManager( val tmpDividerBounds = Rect() getDividerBounds(tmpDividerBounds) dividerView.setup(this, tmpDividerBounds, handleRegionSize, isDarkMode) - t.setRelativeLayer(leash, relativeLeash, 1) - .setPosition( - leash, - dividerBounds.left.toFloat() - maxRoundedCornerRadius, - dividerBounds.top.toFloat(), - ) - .show(leash) - syncQueue.runInSync { transaction -> - transaction.merge(t) - t.close() - } - dividerShown = true + val dividerAnimatorT = transactionSupplier.get() + val dividerAnimator = + ValueAnimator.ofFloat(0f, 1f).apply { + duration = DIVIDER_FADE_IN_ALPHA_DURATION + addUpdateListener { + dividerAnimatorT.setAlpha(leash, animatedValue as Float).apply() + } + addListener( + object : AnimatorListenerAdapter() { + override fun onAnimationStart(animation: Animator) { + dividerAnimatorT + .setRelativeLayer(leash, relativeLeash, 1) + .setPosition( + leash, + dividerBounds.left.toFloat() - maxRoundedCornerRadius, + dividerBounds.top.toFloat(), + ) + .setAlpha(leash, 0f) + .show(leash) + .apply() + } + + override fun onAnimationEnd(animation: Animator) { + dividerAnimatorT.setAlpha(leash, 1f).apply() + dividerShown = true + } + } + ) + } + dividerAnimator.start() viewHost = surfaceControlViewHost - dividerView.addOnLayoutChangeListener(this) tilingDividerView = dividerView updateTouchRegion() + dividerView.addOnLayoutChangeListener(this) } /** Changes divider colour if dark/light mode is toggled. */ @@ -311,4 +331,8 @@ class DesktopTilingDividerWindowManager( ) .maxOf { position -> display.getRoundedCorner(position)?.getRadius() ?: 0 } } + + companion object { + private const val DIVIDER_FADE_IN_ALPHA_DURATION = 300L + } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/tiling/DesktopTilingWindowDecoration.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/tiling/DesktopTilingWindowDecoration.kt index a45df045041f..c3d15df6eae5 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/tiling/DesktopTilingWindowDecoration.kt +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/tiling/DesktopTilingWindowDecoration.kt @@ -133,10 +133,10 @@ class DesktopTilingWindowDecoration( isDarkMode = isTaskInDarkMode(taskInfo) // Observe drag resizing to break tiling if a task is drag resized. desktopModeWindowDecoration.addDragResizeListener(this) - + val callback = { initTilingForDisplayIfNeeded(taskInfo.configuration, isFirstTiledApp) } if (isTiled) { val wct = WindowContainerTransaction().setBounds(taskInfo.token, destinationBounds) - toggleResizeDesktopTaskTransitionHandler.startTransition(wct, currentBounds) + toggleResizeDesktopTaskTransitionHandler.startTransition(wct, currentBounds, callback) } else { // Handle the case where we attempt to snap resize when already snap resized: the task // position won't need to change but we want to animate the surface going back to the @@ -147,10 +147,10 @@ class DesktopTilingWindowDecoration( resizeMetadata.getLeash(), startBounds = currentBounds, endBounds = destinationBounds, + callback, ) } } - initTilingForDisplayIfNeeded(taskInfo.configuration, isFirstTiledApp) return isTiled } diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopActivityOrientationChangeHandlerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopActivityOrientationChangeHandlerTest.kt index 70a30a3ca7a9..d58f8a34c98e 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopActivityOrientationChangeHandlerTest.kt +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopActivityOrientationChangeHandlerTest.kt @@ -188,7 +188,7 @@ class DesktopActivityOrientationChangeHandlerTest : ShellTestCase() { SCREEN_ORIENTATION_LANDSCAPE, ) - verify(resizeTransitionHandler, never()).startTransition(any(), any()) + verify(resizeTransitionHandler, never()).startTransition(any(), any(), any()) } @Test @@ -209,7 +209,7 @@ class DesktopActivityOrientationChangeHandlerTest : ShellTestCase() { SCREEN_ORIENTATION_LANDSCAPE, ) - verify(resizeTransitionHandler, never()).startTransition(any(), any()) + verify(resizeTransitionHandler, never()).startTransition(any(), any(), any()) } @Test @@ -225,7 +225,7 @@ class DesktopActivityOrientationChangeHandlerTest : ShellTestCase() { handler.handleActivityOrientationChange(task, newTask) - verify(resizeTransitionHandler, never()).startTransition(any(), any()) + verify(resizeTransitionHandler, never()).startTransition(any(), any(), any()) } @Test @@ -240,7 +240,7 @@ class DesktopActivityOrientationChangeHandlerTest : ShellTestCase() { SCREEN_ORIENTATION_LANDSCAPE, ) - verify(resizeTransitionHandler, never()).startTransition(any(), any()) + verify(resizeTransitionHandler, never()).startTransition(any(), any(), any()) } @Test @@ -318,7 +318,7 @@ class DesktopActivityOrientationChangeHandlerTest : ShellTestCase() { val arg: ArgumentCaptor<WindowContainerTransaction> = ArgumentCaptor.forClass(WindowContainerTransaction::class.java) verify(resizeTransitionHandler, atLeastOnce()) - .startTransition(capture(arg), eq(currentBounds)) + .startTransition(capture(arg), eq(currentBounds), isNull()) return arg.value } diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt index 0bccde13cabd..857f9bfb7294 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt @@ -5253,7 +5253,8 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase() ) // Assert that task is NOT updated via WCT - verify(toggleResizeDesktopTaskTransitionHandler, never()).startTransition(any(), any()) + verify(toggleResizeDesktopTaskTransitionHandler, never()) + .startTransition(any(), any(), any()) // Assert that task leash is updated via Surface Animations verify(mReturnToDragStartAnimator) .start( @@ -5738,7 +5739,8 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase() InputMethod.TOUCH, ) // Assert that task is NOT updated via WCT - verify(toggleResizeDesktopTaskTransitionHandler, never()).startTransition(any(), any()) + verify(toggleResizeDesktopTaskTransitionHandler, never()) + .startTransition(any(), any(), any()) // Assert that task leash is updated via Surface Animations verify(mReturnToDragStartAnimator) @@ -5835,7 +5837,8 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase() ) // Assert that task is NOT updated via WCT - verify(toggleResizeDesktopTaskTransitionHandler, never()).startTransition(any(), any()) + verify(toggleResizeDesktopTaskTransitionHandler, never()) + .startTransition(any(), any(), any()) verify(mockToast).show() } @@ -6903,7 +6906,7 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase() ): WindowContainerTransaction { val arg = argumentCaptor<WindowContainerTransaction>() verify(toggleResizeDesktopTaskTransitionHandler, atLeastOnce()) - .startTransition(arg.capture(), eq(currentBounds)) + .startTransition(arg.capture(), eq(currentBounds), isNull()) return arg.lastValue } diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/tiling/DesktopTilingDividerWindowManagerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/tiling/DesktopTilingDividerWindowManagerTest.kt index 844205682d31..42eab14042f9 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/tiling/DesktopTilingDividerWindowManagerTest.kt +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/tiling/DesktopTilingDividerWindowManagerTest.kt @@ -70,6 +70,13 @@ class DesktopTilingDividerWindowManagerTest : ShellTestCase() { whenever(context.display).thenReturn(display) whenever(display.getRoundedCorner(any())).thenReturn(roundedCorner) whenever(roundedCorner.radius).thenReturn(CORNER_RADIUS) + whenever(transactionSupplierMock.get()).thenReturn(transaction) + whenever(transaction.show(any())).thenReturn(transaction) + whenever(transaction.setAlpha(any(), any())).thenReturn(transaction) + whenever(transaction.hide(any())).thenReturn(transaction) + whenever(transaction.setRelativeLayer(any(), any(), any())).thenReturn(transaction) + whenever(transaction.setPosition(any(), any(), any())).thenReturn(transaction) + whenever(transaction.remove(any())).thenReturn(transaction) desktopTilingWindowManager = DesktopTilingDividerWindowManager( config, @@ -88,12 +95,6 @@ class DesktopTilingDividerWindowManagerTest : ShellTestCase() { @Test @UiThreadTest fun testWindowManager_isInitialisedAndReleased() { - whenever(transactionSupplierMock.get()).thenReturn(transaction) - whenever(transaction.hide(any())).thenReturn(transaction) - whenever(transaction.setRelativeLayer(any(), any(), any())).thenReturn(transaction) - whenever(transaction.setPosition(any(), any(), any())).thenReturn(transaction) - whenever(transaction.remove(any())).thenReturn(transaction) - desktopTilingWindowManager.generateViewHost(surfaceControl) // Ensure a surfaceControl transaction runs to show the divider. @@ -102,18 +103,11 @@ class DesktopTilingDividerWindowManagerTest : ShellTestCase() { desktopTilingWindowManager.release() verify(transaction, times(1)).hide(any()) verify(transaction, times(1)).remove(any()) - verify(transaction, times(1)).apply() } @Test @UiThreadTest fun testWindowManager_accountsForRoundedCornerDimensions() { - whenever(transactionSupplierMock.get()).thenReturn(transaction) - whenever(transaction.setRelativeLayer(any(), any(), any())).thenReturn(transaction) - whenever(transaction.setRelativeLayer(any(), any(), any())).thenReturn(transaction) - whenever(transaction.setPosition(any(), any(), any())).thenReturn(transaction) - whenever(transaction.show(any())).thenReturn(transaction) - desktopTilingWindowManager.generateViewHost(surfaceControl) // Ensure a surfaceControl transaction runs to show the divider. diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/tiling/DesktopTilingWindowDecorationTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/tiling/DesktopTilingWindowDecorationTest.kt index 399a51e1ed08..bc8faedd77a9 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/tiling/DesktopTilingWindowDecorationTest.kt +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/tiling/DesktopTilingWindowDecorationTest.kt @@ -114,6 +114,7 @@ class DesktopTilingWindowDecorationTest : ShellTestCase() { private val split_divider_width = 10 @Captor private lateinit var wctCaptor: ArgumentCaptor<WindowContainerTransaction> + @Captor private lateinit var callbackCaptor: ArgumentCaptor<(() -> Unit)> @Before fun setUp() { @@ -134,7 +135,7 @@ class DesktopTilingWindowDecorationTest : ShellTestCase() { userRepositories, desktopModeEventLogger, focusTransitionObserver, - mainExecutor + mainExecutor, ) whenever(context.createContextAsUser(any(), any())).thenReturn(context) whenever(userRepositories.current).thenReturn(desktopRepository) @@ -158,7 +159,8 @@ class DesktopTilingWindowDecorationTest : ShellTestCase() { BOUNDS, ) - verify(toggleResizeDesktopTaskTransitionHandler).startTransition(capture(wctCaptor), any()) + verify(toggleResizeDesktopTaskTransitionHandler) + .startTransition(capture(wctCaptor), any(), any()) for (change in wctCaptor.value.changes) { val bounds = change.value.configuration.windowConfiguration.bounds val leftBounds = getLeftTaskBounds() @@ -185,7 +187,8 @@ class DesktopTilingWindowDecorationTest : ShellTestCase() { BOUNDS, ) - verify(toggleResizeDesktopTaskTransitionHandler).startTransition(capture(wctCaptor), any()) + verify(toggleResizeDesktopTaskTransitionHandler) + .startTransition(capture(wctCaptor), any(), any()) for (change in wctCaptor.value.changes) { val bounds = change.value.configuration.windowConfiguration.bounds val leftBounds = getRightTaskBounds() @@ -220,7 +223,7 @@ class DesktopTilingWindowDecorationTest : ShellTestCase() { ) verify(toggleResizeDesktopTaskTransitionHandler, times(1)) - .startTransition(capture(wctCaptor), any()) + .startTransition(capture(wctCaptor), any(), any()) verify(returnToDragStartAnimator, times(1)).start(any(), any(), any(), any(), anyOrNull()) for (change in wctCaptor.value.changes) { val bounds = change.value.configuration.windowConfiguration.bounds @@ -308,9 +311,13 @@ class DesktopTilingWindowDecorationTest : ShellTestCase() { DesktopTasksController.SnapPosition.LEFT, BOUNDS, ) + verify(toggleResizeDesktopTaskTransitionHandler, times(2)) + .startTransition(capture(wctCaptor), any(), capture(callbackCaptor)) + (callbackCaptor.value).invoke() task1.isFocused = true - assertThat(tilingDecoration.moveTiledPairToFront(task1.taskId, isFocusedOnDisplay = true)).isTrue() + assertThat(tilingDecoration.moveTiledPairToFront(task1.taskId, isFocusedOnDisplay = true)) + .isTrue() verify(transitions, times(1)).startTransition(eq(TRANSIT_TO_FRONT), any(), eq(null)) } @@ -341,6 +348,9 @@ class DesktopTilingWindowDecorationTest : ShellTestCase() { ) task1.isFocused = true task3.isFocused = true + verify(toggleResizeDesktopTaskTransitionHandler, times(2)) + .startTransition(capture(wctCaptor), any(), capture(callbackCaptor)) + (callbackCaptor.value).invoke() assertThat(tilingDecoration.moveTiledPairToFront(task3.taskId, true)).isFalse() assertThat(tilingDecoration.moveTiledPairToFront(task1.taskId, true)).isTrue() @@ -372,9 +382,14 @@ class DesktopTilingWindowDecorationTest : ShellTestCase() { DesktopTasksController.SnapPosition.LEFT, BOUNDS, ) - - assertThat(tilingDecoration.moveTiledPairToFront(task3.taskId, isFocusedOnDisplay = true)).isFalse() - assertThat(tilingDecoration.moveTiledPairToFront(task1.taskId, isFocusedOnDisplay = true)).isTrue() + verify(toggleResizeDesktopTaskTransitionHandler, times(2)) + .startTransition(capture(wctCaptor), any(), capture(callbackCaptor)) + (callbackCaptor.value).invoke() + + assertThat(tilingDecoration.moveTiledPairToFront(task3.taskId, isFocusedOnDisplay = true)) + .isFalse() + assertThat(tilingDecoration.moveTiledPairToFront(task1.taskId, isFocusedOnDisplay = true)) + .isTrue() verify(transitions, times(1)).startTransition(eq(TRANSIT_TO_FRONT), any(), eq(null)) } @@ -482,27 +497,29 @@ class DesktopTilingWindowDecorationTest : ShellTestCase() { tilingDecoration.onDividerHandleDragStart(motionEvent) // Log start event for task1 and task2, but the tasks are the same in // this test, so we verify the same log twice. - verify(desktopModeEventLogger, times(2)).logTaskResizingStarted( - ResizeTrigger.TILING_DIVIDER, - DesktopModeEventLogger.Companion.InputMethod.UNKNOWN_INPUT_METHOD, - task1, - BOUNDS.width() / 2, - BOUNDS.height(), - displayController, - ) + verify(desktopModeEventLogger, times(2)) + .logTaskResizingStarted( + ResizeTrigger.TILING_DIVIDER, + DesktopModeEventLogger.Companion.InputMethod.UNKNOWN_INPUT_METHOD, + task1, + BOUNDS.width() / 2, + BOUNDS.height(), + displayController, + ) tilingDecoration.onDividerHandleMoved(BOUNDS, transaction) tilingDecoration.onDividerHandleDragEnd(BOUNDS, transaction, motionEvent) // Log end event for task1 and task2, but the tasks are the same in // this test, so we verify the same log twice. - verify(desktopModeEventLogger, times(2)).logTaskResizingEnded( - ResizeTrigger.TILING_DIVIDER, - DesktopModeEventLogger.Companion.InputMethod.UNKNOWN_INPUT_METHOD, - task1, - BOUNDS.width(), - BOUNDS.height(), - displayController, - ) + verify(desktopModeEventLogger, times(2)) + .logTaskResizingEnded( + ResizeTrigger.TILING_DIVIDER, + DesktopModeEventLogger.Companion.InputMethod.UNKNOWN_INPUT_METHOD, + task1, + BOUNDS.width(), + BOUNDS.height(), + displayController, + ) } @Test |