6bb9d56ded
Create a remote transition supporting alt-tab app-launches (app launches caused by a user using alt-tab to select a minimized app) and any minimization caused by hitting the window limit during such an app launch. Test: manual, and WindowAnimatorTest Bug: 349791584 Flag: com.android.window.flags.enable_desktop_app_launch_alttab_transitions Change-Id: I6474fff351f3d7681ca25cd7331e4955e3d1c6e0
167 lines
6.1 KiB
Kotlin
167 lines
6.1 KiB
Kotlin
/*
|
|
* Copyright (C) 2024 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
package com.android.launcher3.desktop
|
|
|
|
import android.animation.Animator
|
|
import android.animation.AnimatorSet
|
|
import android.animation.ValueAnimator
|
|
import android.content.Context
|
|
import android.os.IBinder
|
|
import android.view.SurfaceControl.Transaction
|
|
import android.view.WindowManager.TRANSIT_OPEN
|
|
import android.view.WindowManager.TRANSIT_TO_BACK
|
|
import android.view.WindowManager.TRANSIT_TO_FRONT
|
|
import android.window.IRemoteTransitionFinishedCallback
|
|
import android.window.RemoteTransitionStub
|
|
import android.window.TransitionInfo
|
|
import android.window.TransitionInfo.Change
|
|
import androidx.core.animation.addListener
|
|
import com.android.app.animation.Interpolators
|
|
import com.android.quickstep.RemoteRunnable
|
|
import java.util.concurrent.Executor
|
|
|
|
/**
|
|
* [android.window.RemoteTransition] for Desktop app launches.
|
|
*
|
|
* This transition supports minimize-changes, i.e. in a launch-transition, if a window is moved back
|
|
* ([android.view.WindowManager.TRANSIT_TO_BACK]) this transition will apply a minimize animation to
|
|
* that window.
|
|
*/
|
|
class DesktopAppLaunchTransition(private val context: Context, private val mainExecutor: Executor) :
|
|
RemoteTransitionStub() {
|
|
|
|
override fun startAnimation(
|
|
token: IBinder,
|
|
info: TransitionInfo,
|
|
t: Transaction,
|
|
transitionFinishedCallback: IRemoteTransitionFinishedCallback,
|
|
) {
|
|
val safeTransitionFinishedCallback = RemoteRunnable {
|
|
transitionFinishedCallback.onTransitionFinished(/* wct= */ null, /* sct= */ null)
|
|
}
|
|
mainExecutor.execute {
|
|
runAnimators(info, safeTransitionFinishedCallback)
|
|
t.apply()
|
|
}
|
|
}
|
|
|
|
private fun runAnimators(info: TransitionInfo, finishedCallback: RemoteRunnable) {
|
|
val animators = mutableListOf<Animator>()
|
|
val animatorFinishedCallback: (Animator) -> Unit = { animator ->
|
|
animators -= animator
|
|
if (animators.isEmpty()) finishedCallback.run()
|
|
}
|
|
animators += createAnimators(info, animatorFinishedCallback)
|
|
animators.forEach { it.start() }
|
|
}
|
|
|
|
private fun createAnimators(
|
|
info: TransitionInfo,
|
|
finishCallback: (Animator) -> Unit,
|
|
): List<Animator> {
|
|
val transaction = Transaction()
|
|
val launchAnimator =
|
|
createLaunchAnimator(getLaunchChange(info), transaction, finishCallback)
|
|
val minimizeChange = getMinimizeChange(info) ?: return listOf(launchAnimator)
|
|
val minimizeAnimator = createMinimizeAnimator(minimizeChange, transaction, finishCallback)
|
|
return listOf(launchAnimator, minimizeAnimator)
|
|
}
|
|
|
|
private fun getLaunchChange(info: TransitionInfo): Change =
|
|
requireNotNull(info.changes.firstOrNull { change -> change.mode in LAUNCH_CHANGE_MODES }) {
|
|
"expected an app launch Change"
|
|
}
|
|
|
|
private fun getMinimizeChange(info: TransitionInfo): Change? =
|
|
info.changes.firstOrNull { change -> change.mode == TRANSIT_TO_BACK }
|
|
|
|
private fun createLaunchAnimator(
|
|
change: Change,
|
|
transaction: Transaction,
|
|
onAnimFinish: (Animator) -> Unit,
|
|
): Animator {
|
|
val boundsAnimator =
|
|
WindowAnimator.createBoundsAnimator(
|
|
context,
|
|
launchBoundsAnimationDef,
|
|
change,
|
|
transaction,
|
|
)
|
|
val alphaAnimator =
|
|
ValueAnimator.ofFloat(0f, 1f).apply {
|
|
duration = LAUNCH_ANIM_ALPHA_DURATION_MS
|
|
interpolator = Interpolators.LINEAR
|
|
addUpdateListener { animation ->
|
|
transaction.setAlpha(change.leash, animation.animatedValue as Float).apply()
|
|
}
|
|
}
|
|
return AnimatorSet().apply {
|
|
playTogether(boundsAnimator, alphaAnimator)
|
|
addListener(onEnd = { animation -> onAnimFinish(animation) })
|
|
}
|
|
}
|
|
|
|
private fun createMinimizeAnimator(
|
|
change: Change,
|
|
transaction: Transaction,
|
|
onAnimFinish: (Animator) -> Unit,
|
|
): Animator {
|
|
val boundsAnimator =
|
|
WindowAnimator.createBoundsAnimator(
|
|
context,
|
|
minimizeBoundsAnimationDef,
|
|
change,
|
|
transaction,
|
|
)
|
|
val alphaAnimator =
|
|
ValueAnimator.ofFloat(1f, 0f).apply {
|
|
duration = MINIMIZE_ANIM_ALPHA_DURATION_MS
|
|
interpolator = Interpolators.LINEAR
|
|
addUpdateListener { animation ->
|
|
transaction.setAlpha(change.leash, animation.animatedValue as Float).apply()
|
|
}
|
|
}
|
|
return AnimatorSet().apply {
|
|
playTogether(boundsAnimator, alphaAnimator)
|
|
addListener(onEnd = { animation -> onAnimFinish(animation) })
|
|
}
|
|
}
|
|
|
|
companion object {
|
|
private val LAUNCH_CHANGE_MODES = intArrayOf(TRANSIT_OPEN, TRANSIT_TO_FRONT)
|
|
|
|
private const val LAUNCH_ANIM_ALPHA_DURATION_MS = 100L
|
|
private const val MINIMIZE_ANIM_ALPHA_DURATION_MS = 100L
|
|
|
|
private val launchBoundsAnimationDef =
|
|
WindowAnimator.BoundsAnimationParams(
|
|
durationMs = 300,
|
|
startOffsetYDp = 12f,
|
|
startScale = 0.97f,
|
|
interpolator = Interpolators.STANDARD_DECELERATE,
|
|
)
|
|
|
|
private val minimizeBoundsAnimationDef =
|
|
WindowAnimator.BoundsAnimationParams(
|
|
durationMs = 200,
|
|
endOffsetYDp = 12f,
|
|
endScale = 0.97f,
|
|
interpolator = Interpolators.STANDARD_ACCELERATE,
|
|
)
|
|
}
|
|
}
|