summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Omar Elmekkawy <mekk@google.com> 2025-03-03 07:47:03 -0800
committer Android (Google) Code Review <android-gerrit@google.com> 2025-03-03 07:47:03 -0800
commitbdf3b1899553ec9db650bfe1ddb89f1e82fef3a3 (patch)
tree333f6fdf3037458add6b95c08d32f381f8670a9f
parent6e7c076dd6b1b92a89a23f69745f51fa8581e7cd (diff)
parent84eea84a337273c9f67e300a52e9f174b3f1c661 (diff)
Merge "Add fade in animation to tiling divider to make it look nicer upon tiling." into main
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/ToggleResizeDesktopTaskTransitionHandler.kt10
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/tiling/DesktopTilingDividerWindowManager.kt52
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/tiling/DesktopTilingWindowDecoration.kt6
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopActivityOrientationChangeHandlerTest.kt10
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt11
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/tiling/DesktopTilingDividerWindowManagerTest.kt20
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/tiling/DesktopTilingWindowDecorationTest.kt65
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