Merge "Add a bubble option to launcher long press menus" into main

This commit is contained in:
Mady Mellor
2024-08-09 17:25:02 +00:00
committed by Android (Google) Code Review
8 changed files with 179 additions and 8 deletions
@@ -16,19 +16,24 @@
package com.android.launcher3.taskbar;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ShortcutInfo;
import android.view.ContextThemeWrapper;
import android.view.LayoutInflater;
import com.android.launcher3.DeviceProfile.OnDeviceProfileChangeListener;
import com.android.launcher3.popup.SystemShortcut;
import com.android.launcher3.util.Themes;
import com.android.launcher3.views.ActivityContext;
import com.android.quickstep.SystemUiProxy;
import java.util.ArrayList;
import java.util.List;
// TODO(b/218912746): Share more behavior to avoid all apps context depending directly on taskbar.
/** Base for common behavior between taskbar window contexts. */
public abstract class BaseTaskbarContext extends ContextThemeWrapper implements ActivityContext {
public abstract class BaseTaskbarContext extends ContextThemeWrapper implements ActivityContext,
SystemShortcut.BubbleActivityStarter {
protected final LayoutInflater mLayoutInflater;
private final List<OnDeviceProfileChangeListener> mDPChangeListeners = new ArrayList<>();
@@ -48,6 +53,18 @@ public abstract class BaseTaskbarContext extends ContextThemeWrapper implements
return mDPChangeListeners;
}
@Override
public void showShortcutBubble(ShortcutInfo info) {
if (info == null) return;
SystemUiProxy.INSTANCE.get(this).showShortcutBubble(info);
}
@Override
public void showAppBubble(Intent intent) {
if (intent == null || intent.getPackage() == null) return;
SystemUiProxy.INSTANCE.get(this).showAppBubble(intent);
}
/** Callback invoked when a drag is initiated within this context. */
public abstract void onDragStart();
@@ -53,6 +53,7 @@ import com.android.quickstep.SystemUiProxy;
import com.android.quickstep.util.LogUtils;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Objects;
@@ -69,6 +70,9 @@ public class TaskbarPopupController implements TaskbarControllers.LoggableTaskba
private static final SystemShortcut.Factory<BaseTaskbarContext>
APP_INFO = SystemShortcut.AppInfo::new;
private static final SystemShortcut.Factory<BaseTaskbarContext>
BUBBLE = SystemShortcut.BubbleShortcut::new;
private final TaskbarActivityContext mContext;
private final PopupDataProvider mPopupDataProvider;
@@ -182,10 +186,13 @@ public class TaskbarPopupController implements TaskbarControllers.LoggableTaskba
// Create a Stream of all applicable system shortcuts
private Stream<SystemShortcut.Factory> getSystemShortcuts() {
// append split options to APP_INFO shortcut, the order here will reflect in the popup
return Stream.concat(
Stream.of(APP_INFO),
mControllers.uiController.getSplitMenuOptions()
);
ArrayList<SystemShortcut.Factory> shortcuts = new ArrayList<>();
shortcuts.add(APP_INFO);
shortcuts.addAll(mControllers.uiController.getSplitMenuOptions().toList());
if (com.android.wm.shell.Flags.enableBubbleAnything()) {
shortcuts.add(BUBBLE);
}
return shortcuts.stream();
}
@Override
@@ -45,6 +45,7 @@ import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCH
import static com.android.launcher3.model.data.ItemInfo.NO_MATCHING_ID;
import static com.android.launcher3.popup.QuickstepSystemShortcut.getSplitSelectShortcutByPosition;
import static com.android.launcher3.popup.SystemShortcut.APP_INFO;
import static com.android.launcher3.popup.SystemShortcut.BUBBLE_SHORTCUT;
import static com.android.launcher3.popup.SystemShortcut.DONT_SUGGEST_APP;
import static com.android.launcher3.popup.SystemShortcut.INSTALL;
import static com.android.launcher3.popup.SystemShortcut.PRIVATE_PROFILE_INSTALL;
@@ -75,6 +76,7 @@ import android.app.ActivityOptions;
import android.content.Context;
import android.content.Intent;
import android.content.IntentSender;
import android.content.pm.ShortcutInfo;
import android.content.res.Configuration;
import android.graphics.Rect;
import android.graphics.RectF;
@@ -215,7 +217,8 @@ import java.util.function.BiConsumer;
import java.util.function.Predicate;
import java.util.stream.Stream;
public class QuickstepLauncher extends Launcher implements RecentsViewContainer {
public class QuickstepLauncher extends Launcher implements RecentsViewContainer,
SystemShortcut.BubbleActivityStarter {
private static final boolean TRACE_LAYOUTS =
SystemProperties.getBoolean("persist.debug.trace_layouts", false);
private static final String TRACE_RELAYOUT_CLASS =
@@ -466,6 +469,9 @@ public class QuickstepLauncher extends Launcher implements RecentsViewContainer
if (Flags.enablePrivateSpace()) {
shortcuts.add(UNINSTALL_APP);
}
if (com.android.wm.shell.Flags.enableBubbleAnything()) {
shortcuts.add(BUBBLE_SHORTCUT);
}
return shortcuts.stream();
}
@@ -1436,6 +1442,18 @@ public class QuickstepLauncher extends Launcher implements RecentsViewContainer
return true;
}
@Override
public void showShortcutBubble(ShortcutInfo info) {
if (info == null) return;
SystemUiProxy.INSTANCE.get(this).showShortcutBubble(info);
}
@Override
public void showAppBubble(Intent intent) {
if (intent == null || intent.getPackage() == null) return;
SystemUiProxy.INSTANCE.get(this).showAppBubble(intent);
}
private static final class LauncherTaskViewController extends
TaskViewTouchController<QuickstepLauncher> {
@@ -47,7 +47,6 @@ import android.view.IRecentsAnimationController;
import android.view.IRecentsAnimationRunner;
import android.view.IRemoteAnimationRunner;
import android.view.MotionEvent;
import android.view.RemoteAnimationAdapter;
import android.view.RemoteAnimationTarget;
import android.view.SurfaceControl;
import android.window.IOnBackInvokedCallback;
@@ -894,6 +893,36 @@ public class SystemUiProxy implements ISystemUiProxy, NavHandle, SafeCloseable {
}
}
/**
* Tells SysUI to show a shortcut bubble.
*
* @param info the shortcut info used to create or identify the bubble.
*/
public void showShortcutBubble(ShortcutInfo info) {
try {
if (mBubbles != null) {
mBubbles.showShortcutBubble(info);
}
} catch (RemoteException e) {
Log.w(TAG, "Failed call show bubble for shortcut");
}
}
/**
* Tells SysUI to show a bubble of an app.
*
* @param intent the intent used to create the bubble.
*/
public void showAppBubble(Intent intent) {
try {
if (mBubbles != null) {
mBubbles.showAppBubble(intent);
}
} catch (RemoteException e) {
Log.w(TAG, "Failed call show bubble for app");
}
}
//
// Splitscreen
//
+25
View File
@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ 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.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="20dp"
android:height="20dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#FF000000"
android:pathData="M23,5v8h-2V5H3v14h10v2v0H3c-1.1,0 -2,-0.9 -2,-2V5c0,-1.1 0.9,-2 2,-2h18C22.1,3 23,3.9 23,5zM10,8v2.59L5.71,6.29L4.29,7.71L8.59,12H6v2h6V8H10zM19,15c-1.66,0 -3,1.34 -3,3s1.34,3 3,3s3,-1.34 3,-3S20.66,15 19,15z"/>
</vector>
+2 -1
View File
@@ -215,7 +215,8 @@
<string name="dismiss_prediction_label">Don\'t suggest app</string>
<!-- Label for pinning predicted app. -->
<string name="pin_prediction">Pin Prediction</string>
<!-- Label for bubbling a launcher item. [CHAR_LIMIT=20] -->
<string name="bubble">Bubble</string>
<!-- Permissions: -->
<skip />
@@ -25,6 +25,7 @@ import android.text.TextUtils;
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.android.launcher3.Flags;
import com.android.launcher3.LauncherSettings;
@@ -97,6 +98,8 @@ public class WorkspaceItemInfo extends ItemInfoWithIcon {
public int options;
@Nullable
private ShortcutInfo mShortcutInfo = null;
public WorkspaceItemInfo() {
itemType = LauncherSettings.Favorites.ITEM_TYPE_APPLICATION;
@@ -175,6 +178,9 @@ public class WorkspaceItemInfo extends ItemInfoWithIcon {
public void updateFromDeepShortcutInfo(@NonNull final ShortcutInfo shortcutInfo,
@NonNull final Context context) {
if (com.android.wm.shell.Flags.enableBubbleAnything()) {
mShortcutInfo = shortcutInfo;
}
// {@link ShortcutInfo#getActivity} can change during an update. Recreate the intent
intent = ShortcutKey.makeIntent(shortcutInfo);
title = shortcutInfo.getShortLabel();
@@ -204,6 +210,11 @@ public class WorkspaceItemInfo extends ItemInfoWithIcon {
: Arrays.stream(persons).map(Person::getKey).sorted().toArray(String[]::new);
}
@Nullable
public ShortcutInfo getDeepShortcutInfo() {
return mShortcutInfo;
}
/**
* {@code true} if the shortcut is disabled due to its app being a lower version.
*/
@@ -11,9 +11,11 @@ import android.app.ActivityOptions;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ShortcutInfo;
import android.graphics.Rect;
import android.os.Process;
import android.os.UserHandle;
import android.util.Log;
import android.view.View;
import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.ImageView;
@@ -25,6 +27,7 @@ import androidx.annotation.Nullable;
import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.AbstractFloatingViewHelper;
import com.android.launcher3.Flags;
import com.android.launcher3.LauncherSettings;
import com.android.launcher3.R;
import com.android.launcher3.SecondaryDropTarget;
import com.android.launcher3.Utilities;
@@ -53,6 +56,7 @@ import java.util.Arrays;
*/
public abstract class SystemShortcut<T extends ActivityContext> extends ItemInfo
implements View.OnClickListener {
private static final String TAG = "SystemShortcut";
private final int mIconResId;
protected final int mLabelResId;
@@ -383,4 +387,63 @@ public abstract class SystemShortcut<T extends ActivityContext> extends ItemInfo
mAbstractFloatingViewHelper.closeOpenViews(mTarget, true,
AbstractFloatingView.TYPE_ALL & ~AbstractFloatingView.TYPE_REBIND_SAFE);
}
public static final Factory<ActivityContext> BUBBLE_SHORTCUT =
(activity, itemInfo, originalView) -> {
if ((itemInfo.itemType != LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT)
&& (itemInfo.itemType != LauncherSettings.Favorites.ITEM_TYPE_APPLICATION)
&& !(itemInfo instanceof WorkspaceItemInfo)) {
return null;
}
return new BubbleShortcut(activity, itemInfo, originalView);
};
public interface BubbleActivityStarter {
/** Tell SysUI to show the provided shortcut in a bubble. */
void showShortcutBubble(ShortcutInfo info);
/** Tell SysUI to show the provided intent in a bubble. */
void showAppBubble(Intent intent);
}
public static class BubbleShortcut<T extends ActivityContext> extends SystemShortcut<T> {
private BubbleActivityStarter mStarter;
public BubbleShortcut(T target, ItemInfo itemInfo, View originalView) {
super(R.drawable.ic_bubble_button, R.string.bubble, target,
itemInfo, originalView);
if (target instanceof BubbleActivityStarter) {
mStarter = (BubbleActivityStarter) target;
}
}
@Override
public void onClick(View view) {
dismissTaskMenuView();
if (mStarter == null) {
Log.w(TAG, "starter null!");
return;
}
// TODO: handle GroupTask (single) items so that recent items in taskbar work
if (mItemInfo instanceof WorkspaceItemInfo) {
WorkspaceItemInfo workspaceItemInfo = (WorkspaceItemInfo) mItemInfo;
ShortcutInfo shortcutInfo = workspaceItemInfo.getDeepShortcutInfo();
if (shortcutInfo != null) {
mStarter.showShortcutBubble(shortcutInfo);
return;
}
}
// If we're here check for an intent
Intent intent = mItemInfo.getIntent();
if (intent != null) {
if (intent.getPackage() == null) {
intent.setPackage(mItemInfo.getTargetPackage());
}
mStarter.showAppBubble(intent);
} else {
Log.w(TAG, "unable to bubble, no intent: " + mItemInfo);
}
}
}
}