Support alt+tab for desktop tasks
Updates keyboard quickswitch logic handle quickswitching while on
desktop. When on desktop, alt+tab moves only between desktop tasks.
Fullscreen tasks are shown in the overflow tile and can be accessed by
going to overview.
TODO:
- when not in desktop and using quickswitch, show the desktop tile as a
combined tile in the row, similar to what is shown in overview
Flag: persist.wm.debug.desktop_mode_2
Bug: 280468885
Test: open some apps on desktop and have some fullscreen apps opened in
the background, when on desktop, observe that alt+tab only switches
between desktop tasks
Test: same setup, but switch to a fullscreen app, observe that alt+tab
only switches between fullscreen tasks and desktop is accessible from
overview
Change-Id: Ib19f2eaa24363bbd0669c8c8c3d99ed9d9118a17
diff --git a/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchController.java b/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchController.java
index 7f655cf..ae1c979 100644
--- a/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchController.java
@@ -22,9 +22,13 @@
import androidx.annotation.Nullable;
import com.android.launcher3.R;
+import com.android.launcher3.statehandlers.DesktopVisibilityController;
import com.android.launcher3.taskbar.overlay.TaskbarOverlayContext;
+import com.android.quickstep.LauncherActivityInterface;
import com.android.quickstep.RecentsModel;
+import com.android.quickstep.util.DesktopTask;
import com.android.quickstep.util.GroupTask;
+import com.android.quickstep.views.DesktopTaskView;
import com.android.systemui.shared.recents.model.Task;
import com.android.systemui.shared.recents.model.ThumbnailData;
@@ -102,21 +106,75 @@
mQuickSwitchViewController = new KeyboardQuickSwitchViewController(
mControllers, overlayContext, keyboardQuickSwitchView, mControllerCallbacks);
+ DesktopVisibilityController desktopController =
+ LauncherActivityInterface.INSTANCE.getDesktopVisibilityController();
+ final boolean onDesktop =
+ DesktopTaskView.DESKTOP_IS_PROTO2_ENABLED
+ && desktopController != null
+ && desktopController.areFreeformTasksVisible();
+
if (mModel.isTaskListValid(mTaskListChangeId)) {
- mQuickSwitchViewController.openQuickSwitchView(
- mTasks, mNumHiddenTasks, /* updateTasks= */ false, currentFocusedIndex);
+ mQuickSwitchViewController.openQuickSwitchView(mTasks,
+ mNumHiddenTasks, /* updateTasks= */ false, currentFocusedIndex, onDesktop);
return;
}
+
mTaskListChangeId = mModel.getTasks((tasks) -> {
- // Only store MAX_TASK tasks, from most to least recent
- Collections.reverse(tasks);
- mTasks = tasks.stream().limit(MAX_TASKS).collect(Collectors.toList());
- mNumHiddenTasks = Math.max(0, tasks.size() - MAX_TASKS);
- mQuickSwitchViewController.openQuickSwitchView(
- mTasks, mNumHiddenTasks, /* updateTasks= */ true, currentFocusedIndex);
+ if (onDesktop) {
+ processLoadedTasksOnDesktop(tasks);
+ } else {
+ processLoadedTasks(tasks);
+ }
+ mQuickSwitchViewController.openQuickSwitchView(mTasks,
+ mNumHiddenTasks, /* updateTasks= */ true, currentFocusedIndex, onDesktop);
});
}
+ private void processLoadedTasks(ArrayList<GroupTask> tasks) {
+ // Only store MAX_TASK tasks, from most to least recent
+ Collections.reverse(tasks);
+
+ // Hide all desktop tasks and show them on the hidden tile
+ int hiddenDesktopTasks = 0;
+ if (DesktopTaskView.DESKTOP_IS_PROTO2_ENABLED) {
+ // TODO(b/280468885): show desktop task as a grouped desktop tile
+ DesktopTask desktopTask = findDesktopTask(tasks);
+ if (desktopTask != null) {
+ hiddenDesktopTasks = desktopTask.tasks.size();
+ tasks = tasks.stream()
+ .filter(t -> !(t instanceof DesktopTask))
+ .collect(Collectors.toCollection(ArrayList<GroupTask>::new));
+ }
+ }
+ mTasks = tasks.stream()
+ .limit(MAX_TASKS)
+ .collect(Collectors.toList());
+ mNumHiddenTasks = Math.max(0, tasks.size() - MAX_TASKS) + hiddenDesktopTasks;
+ }
+
+ private void processLoadedTasksOnDesktop(ArrayList<GroupTask> tasks) {
+ // Find the single desktop task that contains a grouping of desktop tasks
+ DesktopTask desktopTask = findDesktopTask(tasks);
+
+ if (desktopTask != null) {
+ mTasks = desktopTask.tasks.stream().map(GroupTask::new).collect(Collectors.toList());
+ // All other tasks, apart from the grouped desktop task, are hidden
+ mNumHiddenTasks = Math.max(0, tasks.size() - 1);
+ } else {
+ // Desktop tasks were visible, but the recents entry is missing. Fall back to empty list
+ mTasks = Collections.emptyList();
+ mNumHiddenTasks = tasks.size();
+ }
+ }
+
+ @Nullable
+ private DesktopTask findDesktopTask(ArrayList<GroupTask> tasks) {
+ return (DesktopTask) tasks.stream()
+ .filter(t -> t instanceof DesktopTask)
+ .findFirst()
+ .orElse(null);
+ }
+
void closeQuickSwitchView() {
if (mQuickSwitchViewController == null) {
return;
@@ -169,7 +227,7 @@
class ControllerCallbacks {
int getTaskCount() {
- return mNumHiddenTasks == 0 ? mTasks.size() : MAX_TASKS + 1;
+ return mTasks.size() + (mNumHiddenTasks == 0 ? 0 : 1);
}
@Nullable
diff --git a/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchView.java b/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchView.java
index 2cdfb18..15f2914 100644
--- a/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchView.java
+++ b/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchView.java
@@ -190,8 +190,12 @@
ConstraintLayout.LayoutParams lp = new ConstraintLayout.LayoutParams(
width, mTaskViewHeight);
- lp.endToEnd = PARENT_ID;
- lp.startToEnd = previousView.getId();
+ if (previousView == null) {
+ lp.startToStart = PARENT_ID;
+ } else {
+ lp.endToEnd = PARENT_ID;
+ lp.startToEnd = previousView.getId();
+ }
lp.topToTop = PARENT_ID;
lp.bottomToBottom = PARENT_ID;
lp.setMarginEnd(mSpacing);
diff --git a/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchViewController.java b/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchViewController.java
index 7bd8898..edb71a5 100644
--- a/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchViewController.java
@@ -27,6 +27,7 @@
import com.android.launcher3.anim.AnimationSuccessListener;
import com.android.launcher3.taskbar.overlay.TaskbarOverlayContext;
import com.android.launcher3.taskbar.overlay.TaskbarOverlayDragLayer;
+import com.android.quickstep.SystemUiProxy;
import com.android.quickstep.util.GroupTask;
import com.android.systemui.shared.recents.model.Task;
import com.android.systemui.shared.recents.model.ThumbnailData;
@@ -52,6 +53,8 @@
private int mCurrentFocusIndex = -1;
+ private boolean mOnDesktop;
+
protected KeyboardQuickSwitchViewController(
@NonNull TaskbarControllers controllers,
@NonNull TaskbarOverlayContext overlayContext,
@@ -71,10 +74,12 @@
@NonNull List<GroupTask> tasks,
int numHiddenTasks,
boolean updateTasks,
- int currentFocusIndexOverride) {
+ int currentFocusIndexOverride,
+ boolean onDesktop) {
TaskbarOverlayDragLayer dragLayer = mOverlayContext.getDragLayer();
dragLayer.addView(mKeyboardQuickSwitchView);
dragLayer.runOnClickOnce(v -> closeQuickSwitchView(true));
+ mOnDesktop = onDesktop;
mKeyboardQuickSwitchView.applyLoadPlan(
mOverlayContext,
@@ -136,6 +141,10 @@
GroupTask task = mControllerCallbacks.getTaskAt(index);
if (task == null) {
return Math.max(0, index);
+ } else if (mOnDesktop) {
+ UI_HELPER_EXECUTOR.execute(() ->
+ SystemUiProxy.INSTANCE.get(mKeyboardQuickSwitchView.getContext())
+ .showDesktopApp(task.task1.key.id));
} else if (task.task2 == null) {
UI_HELPER_EXECUTOR.execute(() ->
ActivityManagerWrapper.getInstance().startActivityFromRecents(
diff --git a/quickstep/src/com/android/quickstep/OverviewCommandHelper.java b/quickstep/src/com/android/quickstep/OverviewCommandHelper.java
index 07db194..a0d49a4 100644
--- a/quickstep/src/com/android/quickstep/OverviewCommandHelper.java
+++ b/quickstep/src/com/android/quickstep/OverviewCommandHelper.java
@@ -37,7 +37,6 @@
import com.android.launcher3.taskbar.TaskbarUIController;
import com.android.launcher3.util.RunnableList;
import com.android.quickstep.RecentsAnimationCallbacks.RecentsAnimationListener;
-import com.android.quickstep.views.DesktopTaskView;
import com.android.quickstep.views.RecentsView;
import com.android.quickstep.views.TaskView;
import com.android.systemui.shared.recents.model.ThumbnailData;
@@ -186,11 +185,6 @@
&& dp != null
&& (dp.isTablet || dp.isTwoPanels);
- if (DesktopTaskView.DESKTOP_MODE_SUPPORTED) {
- // TODO(b/268075592): add support for quickswitch to/from desktop
- allowQuickSwitch = false;
- }
-
if (cmd.type == TYPE_HIDE) {
if (!allowQuickSwitch) {
return true;
diff --git a/quickstep/src/com/android/quickstep/RecentTasksList.java b/quickstep/src/com/android/quickstep/RecentTasksList.java
index 38ac5bb..34817c0 100644
--- a/quickstep/src/com/android/quickstep/RecentTasksList.java
+++ b/quickstep/src/com/android/quickstep/RecentTasksList.java
@@ -308,7 +308,6 @@
task.setLastSnapshotData(taskInfo);
task.positionInParent = taskInfo.positionInParent;
task.appBounds = taskInfo.configuration.windowConfiguration.getAppBounds();
- // TODO(b/244348395): tasks should be sorted from oldest to most recently used
tasks.add(task);
}
return new DesktopTask(tasks);
diff --git a/quickstep/src/com/android/quickstep/SystemUiProxy.java b/quickstep/src/com/android/quickstep/SystemUiProxy.java
index 380aa69..61fabe4 100644
--- a/quickstep/src/com/android/quickstep/SystemUiProxy.java
+++ b/quickstep/src/com/android/quickstep/SystemUiProxy.java
@@ -1186,6 +1186,19 @@
}
}
+ /**
+ * If task with the given id is on the desktop, bring it to front
+ */
+ public void showDesktopApp(int taskId) {
+ if (mDesktopMode != null) {
+ try {
+ mDesktopMode.showDesktopApp(taskId);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed call showDesktopApp", e);
+ }
+ }
+ }
+
/** Call shell to get number of visible freeform tasks */
public int getVisibleDesktopTaskCount(int displayId) {
if (mDesktopMode != null) {
diff --git a/quickstep/src/com/android/quickstep/util/GroupTask.java b/quickstep/src/com/android/quickstep/util/GroupTask.java
index 2be4f0a..9c49647 100644
--- a/quickstep/src/com/android/quickstep/util/GroupTask.java
+++ b/quickstep/src/com/android/quickstep/util/GroupTask.java
@@ -37,6 +37,10 @@
@TaskView.Type
public final int taskViewType;
+ public GroupTask(@NonNull Task task) {
+ this(task, null, null);
+ }
+
public GroupTask(@NonNull Task t1, @Nullable Task t2, @Nullable SplitBounds splitBounds) {
this(t1, t2, splitBounds, t2 != null ? TaskView.Type.GROUPED : TaskView.Type.SINGLE);
}