Loading quickstep/src/com/android/launcher3/desktop/DesktopAppLaunchTransition.kt 0 → 100644 +166 −0 Original line number Diff line number Diff line /* * 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, ) } } quickstep/src/com/android/launcher3/desktop/WindowAnimator.kt 0 → 100644 +100 −0 Original line number Diff line number Diff line /* * 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.RectEvaluator import android.animation.ValueAnimator import android.content.Context import android.graphics.Rect import android.util.TypedValue import android.view.SurfaceControl import android.view.animation.Interpolator import android.window.TransitionInfo /** Creates animations that can be applied to windows/surfaces. */ object WindowAnimator { /** Parameters defining a window bounds animation. */ data class BoundsAnimationParams( val durationMs: Long, val startOffsetYDp: Float = 0f, val endOffsetYDp: Float = 0f, val startScale: Float = 1f, val endScale: Float = 1f, val interpolator: Interpolator, ) /** * Creates an animator to reposition and scale the bounds of the leash of the given change. * * @param boundsAnimDef the parameters for the animation itself (duration, scale, position) * @param change the change to which the animation should be applied * @param transaction the transaction to apply the animation to */ fun createBoundsAnimator( context: Context, boundsAnimDef: BoundsAnimationParams, change: TransitionInfo.Change, transaction: SurfaceControl.Transaction, ): ValueAnimator { val startBounds = createBounds( context, change.startAbsBounds, boundsAnimDef.startScale, boundsAnimDef.startOffsetYDp, ) val leash = change.leash val endBounds = createBounds( context, change.startAbsBounds, boundsAnimDef.endScale, boundsAnimDef.endOffsetYDp, ) return ValueAnimator.ofObject(RectEvaluator(), startBounds, endBounds).apply { duration = boundsAnimDef.durationMs interpolator = boundsAnimDef.interpolator addUpdateListener { animation -> val animBounds = animation.animatedValue as Rect val animScale = 1 - (1 - boundsAnimDef.endScale) * animation.animatedFraction transaction .setPosition(leash, animBounds.left.toFloat(), animBounds.top.toFloat()) .setScale(leash, animScale, animScale) .apply() } } } private fun createBounds(context: Context, origBounds: Rect, scale: Float, offsetYDp: Float) = Rect(origBounds).apply { check(scale in 0.0..1.0) // Scale the bounds down with an anchor in the center inset( (origBounds.width().toFloat() * (1 - scale) / 2).toInt(), (origBounds.height().toFloat() * (1 - scale) / 2).toInt(), ) val offsetYPx = TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_DIP, offsetYDp, context.resources.displayMetrics, ) .toInt() offset(/* dx= */ 0, offsetYPx) } } quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchViewController.java +12 −2 Original line number Diff line number Diff line Loading @@ -15,6 +15,7 @@ */ package com.android.launcher3.taskbar; import static com.android.launcher3.util.Executors.MAIN_EXECUTOR; import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR; import android.animation.Animator; Loading @@ -31,6 +32,7 @@ import androidx.annotation.Nullable; import com.android.internal.jank.Cuj; import com.android.launcher3.Utilities; import com.android.launcher3.anim.AnimatorListeners; import com.android.launcher3.desktop.DesktopAppLaunchTransition; import com.android.launcher3.taskbar.overlay.TaskbarOverlayContext; import com.android.launcher3.taskbar.overlay.TaskbarOverlayDragLayer; import com.android.launcher3.views.BaseDragLayer; Loading @@ -41,6 +43,7 @@ import com.android.systemui.shared.recents.model.Task; import com.android.systemui.shared.recents.model.ThumbnailData; import com.android.systemui.shared.system.InteractionJankMonitorWrapper; import com.android.systemui.shared.system.QuickStepContract; import com.android.window.flags.Flags; import java.io.PrintWriter; import java.util.List; Loading Loading @@ -181,7 +184,7 @@ public class KeyboardQuickSwitchViewController { Runnable onFinishCallback = () -> InteractionJankMonitorWrapper.end( Cuj.CUJ_LAUNCHER_KEYBOARD_QUICK_SWITCH_APP_LAUNCH); TaskbarActivityContext context = mControllers.taskbarActivityContext; RemoteTransition remoteTransition = new RemoteTransition(new SlideInRemoteTransition( final RemoteTransition slideInTransition = new RemoteTransition(new SlideInRemoteTransition( Utilities.isRtl(mControllers.taskbarActivityContext.getResources()), context.getDeviceProfile().overviewPageSpacing, QuickStepContract.getWindowCornerRadius(context), Loading @@ -195,7 +198,7 @@ public class KeyboardQuickSwitchViewController { SystemUiProxy.INSTANCE.get(mKeyboardQuickSwitchView.getContext()) .showDesktopApps( mKeyboardQuickSwitchView.getDisplay().getDisplayId(), remoteTransition)); slideInTransition)); return -1; } // Even with a valid index, this can be null if the user tries to quick switch before the Loading @@ -208,6 +211,13 @@ public class KeyboardQuickSwitchViewController { // Ignore attempts to run the selected task if it is already running. return -1; } RemoteTransition remoteTransition = slideInTransition; if (mOnDesktop && task.task1.isMinimized && Flags.enableDesktopAppLaunchAlttabTransitions()) { // This app is being unminimized - use our own transition runner. remoteTransition = new RemoteTransition( new DesktopAppLaunchTransition(context, MAIN_EXECUTOR)); } mControllers.taskbarActivityContext.handleGroupTaskLaunch( task, remoteTransition, Loading quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java +16 −7 Original line number Diff line number Diff line Loading @@ -1240,7 +1240,8 @@ public class TaskbarActivityContext extends BaseTaskbarContext { } } else if (tag instanceof TaskItemInfo info) { UI_HELPER_EXECUTOR.execute(() -> SystemUiProxy.INSTANCE.get(this).showDesktopApp(info.getTaskId())); SystemUiProxy.INSTANCE.get(this).showDesktopApp( info.getTaskId(), /* remoteTransition= */ null)); mControllers.taskbarStashController.updateAndAnimateTransientTaskbar( /* stash= */ true); } else if (tag instanceof WorkspaceItemInfo) { Loading Loading @@ -1331,7 +1332,8 @@ public class TaskbarActivityContext extends BaseTaskbarContext { GroupTask task, @Nullable RemoteTransition remoteTransition, boolean onDesktop) { handleGroupTaskLaunch(task, remoteTransition, onDesktop, null, null); handleGroupTaskLaunch(task, remoteTransition, onDesktop, /* onStartCallback= */ null, /* onFinishCallback= */ null); } /** Loading @@ -1355,17 +1357,24 @@ public class TaskbarActivityContext extends BaseTaskbarContext { UI_HELPER_EXECUTOR.execute(() -> SystemUiProxy.INSTANCE.get(this).showDesktopApps(getDisplay().getDisplayId(), remoteTransition)); } else if (onDesktop) { return; } if (onDesktop) { boolean useRemoteTransition = task.task1.isMinimized && com.android.window.flags.Flags.enableDesktopAppLaunchAlttabTransitions(); UI_HELPER_EXECUTOR.execute(() -> { if (onStartCallback != null) { onStartCallback.run(); } SystemUiProxy.INSTANCE.get(this).showDesktopApp(task.task1.key.id); SystemUiProxy.INSTANCE.get(this).showDesktopApp( task.task1.key.id, useRemoteTransition ? remoteTransition : null); if (onFinishCallback != null) { onFinishCallback.run(); } }); } else if (task.task2 == null) { return; } if (task.task2 == null) { UI_HELPER_EXECUTOR.execute(() -> { ActivityOptions activityOptions = makeDefaultActivityOptions(SPLASH_SCREEN_STYLE_UNDEFINED).options; Loading @@ -1374,9 +1383,9 @@ public class TaskbarActivityContext extends BaseTaskbarContext { ActivityManagerWrapper.getInstance().startActivityFromRecents( task.task1.key, activityOptions); }); } else { mControllers.uiController.launchSplitTasks(task, remoteTransition); return; } mControllers.uiController.launchSplitTasks(task, remoteTransition); } /** Loading quickstep/src/com/android/quickstep/SystemUiProxy.java +2 −2 Original line number Diff line number Diff line Loading @@ -1426,10 +1426,10 @@ public class SystemUiProxy implements ISystemUiProxy, NavHandle, SafeCloseable { /** * If task with the given id is on the desktop, bring it to front */ public void showDesktopApp(int taskId) { public void showDesktopApp(int taskId, @Nullable RemoteTransition transition) { if (mDesktopMode != null) { try { mDesktopMode.showDesktopApp(taskId); mDesktopMode.showDesktopApp(taskId, transition); } catch (RemoteException e) { Log.w(TAG, "Failed call showDesktopApp", e); } Loading Loading
quickstep/src/com/android/launcher3/desktop/DesktopAppLaunchTransition.kt 0 → 100644 +166 −0 Original line number Diff line number Diff line /* * 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, ) } }
quickstep/src/com/android/launcher3/desktop/WindowAnimator.kt 0 → 100644 +100 −0 Original line number Diff line number Diff line /* * 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.RectEvaluator import android.animation.ValueAnimator import android.content.Context import android.graphics.Rect import android.util.TypedValue import android.view.SurfaceControl import android.view.animation.Interpolator import android.window.TransitionInfo /** Creates animations that can be applied to windows/surfaces. */ object WindowAnimator { /** Parameters defining a window bounds animation. */ data class BoundsAnimationParams( val durationMs: Long, val startOffsetYDp: Float = 0f, val endOffsetYDp: Float = 0f, val startScale: Float = 1f, val endScale: Float = 1f, val interpolator: Interpolator, ) /** * Creates an animator to reposition and scale the bounds of the leash of the given change. * * @param boundsAnimDef the parameters for the animation itself (duration, scale, position) * @param change the change to which the animation should be applied * @param transaction the transaction to apply the animation to */ fun createBoundsAnimator( context: Context, boundsAnimDef: BoundsAnimationParams, change: TransitionInfo.Change, transaction: SurfaceControl.Transaction, ): ValueAnimator { val startBounds = createBounds( context, change.startAbsBounds, boundsAnimDef.startScale, boundsAnimDef.startOffsetYDp, ) val leash = change.leash val endBounds = createBounds( context, change.startAbsBounds, boundsAnimDef.endScale, boundsAnimDef.endOffsetYDp, ) return ValueAnimator.ofObject(RectEvaluator(), startBounds, endBounds).apply { duration = boundsAnimDef.durationMs interpolator = boundsAnimDef.interpolator addUpdateListener { animation -> val animBounds = animation.animatedValue as Rect val animScale = 1 - (1 - boundsAnimDef.endScale) * animation.animatedFraction transaction .setPosition(leash, animBounds.left.toFloat(), animBounds.top.toFloat()) .setScale(leash, animScale, animScale) .apply() } } } private fun createBounds(context: Context, origBounds: Rect, scale: Float, offsetYDp: Float) = Rect(origBounds).apply { check(scale in 0.0..1.0) // Scale the bounds down with an anchor in the center inset( (origBounds.width().toFloat() * (1 - scale) / 2).toInt(), (origBounds.height().toFloat() * (1 - scale) / 2).toInt(), ) val offsetYPx = TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_DIP, offsetYDp, context.resources.displayMetrics, ) .toInt() offset(/* dx= */ 0, offsetYPx) } }
quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchViewController.java +12 −2 Original line number Diff line number Diff line Loading @@ -15,6 +15,7 @@ */ package com.android.launcher3.taskbar; import static com.android.launcher3.util.Executors.MAIN_EXECUTOR; import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR; import android.animation.Animator; Loading @@ -31,6 +32,7 @@ import androidx.annotation.Nullable; import com.android.internal.jank.Cuj; import com.android.launcher3.Utilities; import com.android.launcher3.anim.AnimatorListeners; import com.android.launcher3.desktop.DesktopAppLaunchTransition; import com.android.launcher3.taskbar.overlay.TaskbarOverlayContext; import com.android.launcher3.taskbar.overlay.TaskbarOverlayDragLayer; import com.android.launcher3.views.BaseDragLayer; Loading @@ -41,6 +43,7 @@ import com.android.systemui.shared.recents.model.Task; import com.android.systemui.shared.recents.model.ThumbnailData; import com.android.systemui.shared.system.InteractionJankMonitorWrapper; import com.android.systemui.shared.system.QuickStepContract; import com.android.window.flags.Flags; import java.io.PrintWriter; import java.util.List; Loading Loading @@ -181,7 +184,7 @@ public class KeyboardQuickSwitchViewController { Runnable onFinishCallback = () -> InteractionJankMonitorWrapper.end( Cuj.CUJ_LAUNCHER_KEYBOARD_QUICK_SWITCH_APP_LAUNCH); TaskbarActivityContext context = mControllers.taskbarActivityContext; RemoteTransition remoteTransition = new RemoteTransition(new SlideInRemoteTransition( final RemoteTransition slideInTransition = new RemoteTransition(new SlideInRemoteTransition( Utilities.isRtl(mControllers.taskbarActivityContext.getResources()), context.getDeviceProfile().overviewPageSpacing, QuickStepContract.getWindowCornerRadius(context), Loading @@ -195,7 +198,7 @@ public class KeyboardQuickSwitchViewController { SystemUiProxy.INSTANCE.get(mKeyboardQuickSwitchView.getContext()) .showDesktopApps( mKeyboardQuickSwitchView.getDisplay().getDisplayId(), remoteTransition)); slideInTransition)); return -1; } // Even with a valid index, this can be null if the user tries to quick switch before the Loading @@ -208,6 +211,13 @@ public class KeyboardQuickSwitchViewController { // Ignore attempts to run the selected task if it is already running. return -1; } RemoteTransition remoteTransition = slideInTransition; if (mOnDesktop && task.task1.isMinimized && Flags.enableDesktopAppLaunchAlttabTransitions()) { // This app is being unminimized - use our own transition runner. remoteTransition = new RemoteTransition( new DesktopAppLaunchTransition(context, MAIN_EXECUTOR)); } mControllers.taskbarActivityContext.handleGroupTaskLaunch( task, remoteTransition, Loading
quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java +16 −7 Original line number Diff line number Diff line Loading @@ -1240,7 +1240,8 @@ public class TaskbarActivityContext extends BaseTaskbarContext { } } else if (tag instanceof TaskItemInfo info) { UI_HELPER_EXECUTOR.execute(() -> SystemUiProxy.INSTANCE.get(this).showDesktopApp(info.getTaskId())); SystemUiProxy.INSTANCE.get(this).showDesktopApp( info.getTaskId(), /* remoteTransition= */ null)); mControllers.taskbarStashController.updateAndAnimateTransientTaskbar( /* stash= */ true); } else if (tag instanceof WorkspaceItemInfo) { Loading Loading @@ -1331,7 +1332,8 @@ public class TaskbarActivityContext extends BaseTaskbarContext { GroupTask task, @Nullable RemoteTransition remoteTransition, boolean onDesktop) { handleGroupTaskLaunch(task, remoteTransition, onDesktop, null, null); handleGroupTaskLaunch(task, remoteTransition, onDesktop, /* onStartCallback= */ null, /* onFinishCallback= */ null); } /** Loading @@ -1355,17 +1357,24 @@ public class TaskbarActivityContext extends BaseTaskbarContext { UI_HELPER_EXECUTOR.execute(() -> SystemUiProxy.INSTANCE.get(this).showDesktopApps(getDisplay().getDisplayId(), remoteTransition)); } else if (onDesktop) { return; } if (onDesktop) { boolean useRemoteTransition = task.task1.isMinimized && com.android.window.flags.Flags.enableDesktopAppLaunchAlttabTransitions(); UI_HELPER_EXECUTOR.execute(() -> { if (onStartCallback != null) { onStartCallback.run(); } SystemUiProxy.INSTANCE.get(this).showDesktopApp(task.task1.key.id); SystemUiProxy.INSTANCE.get(this).showDesktopApp( task.task1.key.id, useRemoteTransition ? remoteTransition : null); if (onFinishCallback != null) { onFinishCallback.run(); } }); } else if (task.task2 == null) { return; } if (task.task2 == null) { UI_HELPER_EXECUTOR.execute(() -> { ActivityOptions activityOptions = makeDefaultActivityOptions(SPLASH_SCREEN_STYLE_UNDEFINED).options; Loading @@ -1374,9 +1383,9 @@ public class TaskbarActivityContext extends BaseTaskbarContext { ActivityManagerWrapper.getInstance().startActivityFromRecents( task.task1.key, activityOptions); }); } else { mControllers.uiController.launchSplitTasks(task, remoteTransition); return; } mControllers.uiController.launchSplitTasks(task, remoteTransition); } /** Loading
quickstep/src/com/android/quickstep/SystemUiProxy.java +2 −2 Original line number Diff line number Diff line Loading @@ -1426,10 +1426,10 @@ public class SystemUiProxy implements ISystemUiProxy, NavHandle, SafeCloseable { /** * If task with the given id is on the desktop, bring it to front */ public void showDesktopApp(int taskId) { public void showDesktopApp(int taskId, @Nullable RemoteTransition transition) { if (mDesktopMode != null) { try { mDesktopMode.showDesktopApp(taskId); mDesktopMode.showDesktopApp(taskId, transition); } catch (RemoteException e) { Log.w(TAG, "Failed call showDesktopApp", e); } Loading