From 8e0ed4b01bd4f3c17b69a95a2fbe86dedb3f6e23 Mon Sep 17 00:00:00 2001 From: Saumya Prakash Date: Fri, 6 Sep 2024 22:40:47 +0000 Subject: [PATCH] Add "New Window" option to Taskbar menu. This change adds a new menu option to Taskbar that is invoked when long pressing an icon. It createds a new instance for an app if the app supports multi instance in Desktop Mode. Bug: 315344726 Test: Manual Flag: com.android.launcher3.enable_multi_instance_menu_taskbar Change-Id: Ibc42fbb1ad485496cd938af730b86e051cea559a --- .../taskbar/NewWindowTaskbarShortcut.kt | 47 +++++++++++++++ .../taskbar/TaskbarModelCallbacks.java | 1 + .../taskbar/TaskbarPopupController.java | 60 ++++++++++++++++++- ...esktop_mode_ic_taskbar_menu_new_window.xml | 25 ++++++++ res/values/strings.xml | 3 + 5 files changed, 135 insertions(+), 1 deletion(-) create mode 100644 quickstep/src/com/android/launcher3/taskbar/NewWindowTaskbarShortcut.kt create mode 100644 res/drawable/desktop_mode_ic_taskbar_menu_new_window.xml diff --git a/quickstep/src/com/android/launcher3/taskbar/NewWindowTaskbarShortcut.kt b/quickstep/src/com/android/launcher3/taskbar/NewWindowTaskbarShortcut.kt new file mode 100644 index 0000000000..dc66e0b7ca --- /dev/null +++ b/quickstep/src/com/android/launcher3/taskbar/NewWindowTaskbarShortcut.kt @@ -0,0 +1,47 @@ +/* + * 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.taskbar + +import android.content.Context +import android.content.Intent.FLAG_ACTIVITY_MULTIPLE_TASK +import android.view.View +import com.android.launcher3.AbstractFloatingView +import com.android.launcher3.R +import com.android.launcher3.model.data.ItemInfo +import com.android.launcher3.popup.SystemShortcut +import com.android.launcher3.views.ActivityContext + +/** + * A single menu item shortcut to execute creating a new instance of an app. Default interaction for + * [onClick] is to launch the app in full screen or as a floating window in Desktop Mode. + */ +class NewWindowTaskbarShortcut(target: T, itemInfo: ItemInfo?, originalView: View?) : + SystemShortcut( + R.drawable.desktop_mode_ic_taskbar_menu_new_window, + R.string.new_window_option_taskbar, + target, + itemInfo, + originalView + ) where T : Context?, T : ActivityContext? { + + override fun onClick(v: View?) { + val intent = mItemInfo.intent ?: return + intent.addFlags(FLAG_ACTIVITY_MULTIPLE_TASK) + mTarget?.startActivitySafely(v, intent, mItemInfo) + AbstractFloatingView.closeAllOpenViews(mTarget) + } +} diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarModelCallbacks.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarModelCallbacks.java index 5024cd8817..bdefea6b22 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarModelCallbacks.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarModelCallbacks.java @@ -250,6 +250,7 @@ public class TaskbarModelCallbacks implements Map packageUserKeytoUidMap) { Preconditions.assertUIThread(); mControllers.taskbarAllAppsController.setApps(apps, flags, packageUserKeytoUidMap); + mControllers.taskbarPopupController.setApps(apps); } protected void dumpLogs(String prefix, PrintWriter pw) { diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarPopupController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarPopupController.java index 332eb9519e..0cce166c53 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarPopupController.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarPopupController.java @@ -15,6 +15,7 @@ */ package com.android.launcher3.taskbar; +import static com.android.launcher3.model.data.AppInfo.COMPONENT_KEY_COMPARATOR; import static com.android.launcher3.util.SplitConfigurationOptions.getLogEventForPosition; import android.content.Intent; @@ -29,11 +30,13 @@ import androidx.annotation.NonNull; import com.android.internal.logging.InstanceId; import com.android.launcher3.AbstractFloatingView; import com.android.launcher3.BubbleTextView; +import com.android.launcher3.Flags; import com.android.launcher3.LauncherSettings; import com.android.launcher3.R; import com.android.launcher3.dot.FolderDotInfo; import com.android.launcher3.folder.Folder; import com.android.launcher3.folder.FolderIcon; +import com.android.launcher3.model.data.AppInfo; import com.android.launcher3.model.data.FolderInfo; import com.android.launcher3.model.data.ItemInfo; import com.android.launcher3.model.data.WorkspaceItemInfo; @@ -51,9 +54,11 @@ import com.android.launcher3.util.SplitConfigurationOptions.SplitPositionOption; import com.android.launcher3.views.ActivityContext; import com.android.quickstep.SystemUiProxy; import com.android.quickstep.util.LogUtils; +import com.android.wm.shell.shared.desktopmode.DesktopModeStatus; import java.io.PrintWriter; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Objects; @@ -79,6 +84,7 @@ public class TaskbarPopupController implements TaskbarControllers.LoggableTaskba // Initialized in init. private TaskbarControllers mControllers; private boolean mAllowInitialSplitSelection; + private AppInfo[] mAppInfosList; public TaskbarPopupController(TaskbarActivityContext context) { mContext = context; @@ -195,6 +201,10 @@ public class TaskbarPopupController implements TaskbarControllers.LoggableTaskba if (com.android.wm.shell.Flags.enableBubbleAnything()) { shortcuts.add(BUBBLE); } + if (Flags.enableMultiInstanceMenuTaskbar() + && DesktopModeStatus.canEnterDesktopMode(mContext)) { + shortcuts.addAll(getMultiInstanceMenuOptions().toList()); + } return shortcuts.stream(); } @@ -258,7 +268,55 @@ public class TaskbarPopupController implements TaskbarControllers.LoggableTaskba originalView, position, mAllowInitialSplitSelection); } - /** + /** + * Set the list of AppInfos to be able to pull from later + */ + public void setApps(AppInfo[] apps) { + mAppInfosList = apps; + } + + /** + * Finds and returns an AppInfo object from a list, using its ComponentKey for identification. + * Based off of {@link com.android.launcher3.allapps.AllAppsStore#getApp(ComponentKey)} + * since we cannot access AllAppsStore from here. + */ + public AppInfo getApp(ComponentKey key) { + if (key == null) { + return null; + } + AppInfo tempInfo = new AppInfo(); + tempInfo.componentName = key.componentName; + tempInfo.user = key.user; + int index = Arrays.binarySearch(mAppInfosList, tempInfo, COMPONENT_KEY_COMPARATOR); + return index < 0 ? null : mAppInfosList[index]; + } + + /** + * Returns a stream of Multi Instance menu options if an app supports it. + */ + Stream> getMultiInstanceMenuOptions() { + SystemShortcut.Factory factory = createNewWindowShortcutFactory(); + return factory != null ? Stream.of(factory) : Stream.empty(); + + } + + /** + * Creates a factory function representing a "New Window" menu item only if the calling app + * supports multi-instance. + * @return A factory function to be used in populating the long-press menu. + */ + SystemShortcut.Factory createNewWindowShortcutFactory() { + return (context, itemInfo, originalView) -> { + ComponentKey key = itemInfo.getComponentKey(); + AppInfo app = getApp(key); + if (app != null && app.supportsMultiInstance()) { + return new NewWindowTaskbarShortcut<>(context, itemInfo, originalView); + } + return null; + }; + } + + /** * A single menu item ("Split left," "Split right," or "Split top") that executes a split * from the taskbar, as if the user performed a drag and drop split. * Includes an onClick method that initiates the actual split. diff --git a/res/drawable/desktop_mode_ic_taskbar_menu_new_window.xml b/res/drawable/desktop_mode_ic_taskbar_menu_new_window.xml new file mode 100644 index 0000000000..b96a596e94 --- /dev/null +++ b/res/drawable/desktop_mode_ic_taskbar_menu_new_window.xml @@ -0,0 +1,25 @@ + + + + + diff --git a/res/values/strings.xml b/res/values/strings.xml index fd724a5553..9d0602169c 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -45,6 +45,9 @@ App info for %1$s Usage settings for %1$s + + New Window + Save app pair