Add task menu item to move task to external display

Call SystemUiProxy.moveToExternalDisplay to move existing Overview task to desktop in external display

Bug: 372872848
Test: atest
NexusLauncherTests:com.android.quickstep.ExternalDisplaySystemShortcutTest
Flag: com.android.window.flags.move_to_external_display_shortcut
Change-Id: I096a9839956ab5cab86bd0aaabc625a8587ca42a
This commit is contained in:
Graciela Wissen Putri
2024-10-14 15:14:01 +00:00
parent 9777937d41
commit 2f4ccc63b6
9 changed files with 345 additions and 0 deletions
@@ -66,6 +66,11 @@ class DesktopRecentsTransitionController(
systemUiProxy.moveToDesktop(taskId, transitionSource)
}
/** Move task to external display from recents view */
fun moveToExternalDisplay(taskId: Int) {
systemUiProxy.moveToExternalDisplay(taskId)
}
private class RemoteDesktopLaunchTransitionRunner(
private val desktopTaskView: DesktopTaskView,
private val animated: Boolean,
@@ -0,0 +1,86 @@
/*
* 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.quickstep
import android.view.View
import com.android.launcher3.AbstractFloatingViewHelper
import com.android.launcher3.R
import com.android.launcher3.logging.StatsLogManager.LauncherEvent
import com.android.launcher3.popup.SystemShortcut
import com.android.quickstep.views.RecentsView
import com.android.quickstep.views.RecentsViewContainer
import com.android.quickstep.views.TaskContainer
import com.android.window.flags.Flags
import com.android.wm.shell.shared.desktopmode.DesktopModeStatus
/** A menu item that allows the user to move the current app into external display. */
class ExternalDisplaySystemShortcut(
container: RecentsViewContainer,
abstractFloatingViewHelper: AbstractFloatingViewHelper,
private val taskContainer: TaskContainer,
) :
SystemShortcut<RecentsViewContainer>(
R.drawable.ic_external_display,
R.string.recent_task_option_external_display,
container,
taskContainer.itemInfo,
taskContainer.taskView,
abstractFloatingViewHelper,
) {
override fun onClick(view: View) {
dismissTaskMenuView()
val recentsView = mTarget.getOverviewPanel<RecentsView<*, *>>()
recentsView.moveTaskToExternalDisplay(taskContainer) {
mTarget.statsLogManager
.logger()
.withItemInfo(taskContainer.itemInfo)
.log(LauncherEvent.LAUNCHER_SYSTEM_SHORTCUT_EXTERNAL_DISPLAY_TAP)
}
}
companion object {
@JvmOverloads
/**
* Creates a factory for creating move task to external display system shortcuts in
* [com.android.quickstep.TaskOverlayFactory].
*/
fun createFactory(
abstractFloatingViewHelper: AbstractFloatingViewHelper = AbstractFloatingViewHelper()
): TaskShortcutFactory =
object : TaskShortcutFactory {
override fun getShortcuts(
container: RecentsViewContainer,
taskContainer: TaskContainer,
): List<ExternalDisplaySystemShortcut>? {
return if (
DesktopModeStatus.canEnterDesktopMode(container.asContext()) &&
Flags.moveToExternalDisplayShortcut()
)
listOf(
ExternalDisplaySystemShortcut(
container,
abstractFloatingViewHelper,
taskContainer,
)
)
else null
}
override fun showForGroupedTask() = true
}
}
}
@@ -1493,6 +1493,17 @@ public class SystemUiProxy implements ISystemUiProxy, NavHandle, SafeCloseable {
}
}
/** Call shell to move a task with given `taskId` to external display. */
public void moveToExternalDisplay(int taskId) {
if (mDesktopMode != null) {
try {
mDesktopMode.moveToExternalDisplay(taskId);
} catch (RemoteException e) {
Log.w(TAG, "Failed call moveToExternalDisplay", e);
}
}
}
//
// Unfold transition
//
@@ -116,6 +116,7 @@ public class TaskOverlayFactory implements ResourceBasedOverride {
TaskShortcutFactory.INSTALL,
TaskShortcutFactory.FREE_FORM,
DesktopSystemShortcut.Companion.createFactory(),
ExternalDisplaySystemShortcut.Companion.createFactory(),
TaskShortcutFactory.WELLBEING,
TaskShortcutFactory.SAVE_APP_PAIR,
TaskShortcutFactory.SCREENSHOT,
@@ -6673,6 +6673,26 @@ public abstract class RecentsView<
successCallback.run();
}
/**
* Move the provided task into external display and invoke {@code successCallback} if succeeded.
*/
public void moveTaskToExternalDisplay(TaskContainer taskContainer, Runnable successCallback) {
if (!DesktopModeStatus.canEnterDesktopMode(mContext)) {
return;
}
switchToScreenshot(() -> finishRecentsAnimation(/* toRecents= */true, /* shouldPip= */false,
() -> moveTaskToDesktopInternal(taskContainer, successCallback)));
}
private void moveTaskToDesktopInternal(TaskContainer taskContainer, Runnable successCallback) {
if (mDesktopRecentsTransitionController == null) {
return;
}
mDesktopRecentsTransitionController.moveToExternalDisplay(taskContainer.getTask().key.id);
successCallback.run();
}
// Logs when the orientation of Overview changes. We log both real and fake orientation changes.
private void logOrientationChanged() {
// Only log when Overview is showing.