Separating SystemShortcut and Factory
> This makes easier to extend the factory and callbacks separately
> Availability checks are only performed once when getting the shortcut
Change-Id: I413541eabfb2b9e987c852d5171c6696b1853958
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskOverlayFactory.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskOverlayFactory.java
index 17457aa..298b0ff 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskOverlayFactory.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskOverlayFactory.java
@@ -19,11 +19,11 @@
import static com.android.launcher3.util.MainThreadInitializedObject.forOverride;
import android.graphics.Matrix;
-import android.view.View;
import com.android.launcher3.BaseActivity;
import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.R;
+import com.android.launcher3.popup.SystemShortcut;
import com.android.launcher3.util.MainThreadInitializedObject;
import com.android.launcher3.util.ResourceBasedOverride;
import com.android.quickstep.views.TaskThumbnailView;
@@ -40,25 +40,24 @@
public class TaskOverlayFactory implements ResourceBasedOverride {
/** Note that these will be shown in order from top to bottom, if available for the task. */
- private static final TaskSystemShortcut[] MENU_OPTIONS = new TaskSystemShortcut[]{
- new TaskSystemShortcut.AppInfo(),
- new TaskSystemShortcut.SplitScreen(),
- new TaskSystemShortcut.Pin(),
- new TaskSystemShortcut.Install(),
- new TaskSystemShortcut.Freeform()
+ private static final TaskShortcutFactory[] MENU_OPTIONS = new TaskShortcutFactory[]{
+ TaskShortcutFactory.APP_INFO,
+ TaskShortcutFactory.SPLIT_SCREEN,
+ TaskShortcutFactory.PIN,
+ TaskShortcutFactory.INSTALL,
+ TaskShortcutFactory.FREE_FORM
};
public static final MainThreadInitializedObject<TaskOverlayFactory> INSTANCE =
forOverride(TaskOverlayFactory.class, R.string.task_overlay_factory_class);
- public List<TaskSystemShortcut> getEnabledShortcuts(TaskView taskView) {
- final ArrayList<TaskSystemShortcut> shortcuts = new ArrayList<>();
+ public List<SystemShortcut> getEnabledShortcuts(TaskView taskView) {
+ final ArrayList<SystemShortcut> shortcuts = new ArrayList<>();
final BaseDraggingActivity activity = BaseActivity.fromContext(taskView.getContext());
- for (TaskSystemShortcut menuOption : MENU_OPTIONS) {
- View.OnClickListener onClickListener =
- menuOption.getOnClickListener(activity, taskView);
- if (onClickListener != null) {
- shortcuts.add(menuOption);
+ for (TaskShortcutFactory menuOption : MENU_OPTIONS) {
+ SystemShortcut shortcut = menuOption.getShortcut(activity, taskView);
+ if (shortcut != null) {
+ shortcuts.add(shortcut);
}
}
return shortcuts;
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskShortcutFactory.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskShortcutFactory.java
new file mode 100644
index 0000000..a3a1d6d
--- /dev/null
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskShortcutFactory.java
@@ -0,0 +1,312 @@
+/*
+ * Copyright (C) 2018 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 static android.view.Display.DEFAULT_DISPLAY;
+
+import static com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch.TAP;
+
+import android.app.Activity;
+import android.app.ActivityOptions;
+import android.content.ComponentName;
+import android.content.Intent;
+import android.graphics.Bitmap;
+import android.graphics.Color;
+import android.graphics.Rect;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.UserHandle;
+import android.view.View;
+
+import com.android.launcher3.BaseDraggingActivity;
+import com.android.launcher3.DeviceProfile;
+import com.android.launcher3.R;
+import com.android.launcher3.WorkspaceItemInfo;
+import com.android.launcher3.popup.SystemShortcut;
+import com.android.launcher3.popup.SystemShortcut.AppInfo;
+import com.android.launcher3.userevent.nano.LauncherLogProto;
+import com.android.launcher3.util.Executors;
+import com.android.launcher3.util.InstantAppResolver;
+import com.android.quickstep.views.RecentsView;
+import com.android.quickstep.views.TaskThumbnailView;
+import com.android.quickstep.views.TaskView;
+import com.android.systemui.shared.recents.model.Task;
+import com.android.systemui.shared.recents.view.AppTransitionAnimationSpecCompat;
+import com.android.systemui.shared.recents.view.AppTransitionAnimationSpecsFuture;
+import com.android.systemui.shared.recents.view.RecentsTransition;
+import com.android.systemui.shared.system.ActivityCompat;
+import com.android.systemui.shared.system.ActivityManagerWrapper;
+import com.android.systemui.shared.system.ActivityOptionsCompat;
+import com.android.systemui.shared.system.WindowManagerWrapper;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.function.Consumer;
+
+/**
+ * Represents a system shortcut that can be shown for a recent task.
+ */
+public interface TaskShortcutFactory {
+
+ SystemShortcut getShortcut(BaseDraggingActivity activity, TaskView view);
+
+ static WorkspaceItemInfo dummyInfo(TaskView view) {
+ Task task = view.getTask();
+
+ WorkspaceItemInfo dummyInfo = new WorkspaceItemInfo();
+ dummyInfo.intent = new Intent();
+ ComponentName component = task.getTopComponent();
+ dummyInfo.intent.setComponent(component);
+ dummyInfo.user = UserHandle.of(task.key.userId);
+ dummyInfo.title = TaskUtils.getTitle(view.getContext(), task);
+ return dummyInfo;
+ }
+
+ TaskShortcutFactory APP_INFO = (activity, view) -> new AppInfo(activity, dummyInfo(view));
+
+ abstract class MultiWindowFactory implements TaskShortcutFactory {
+
+ private final int mIconRes;
+ private final int mTextRes;
+
+ MultiWindowFactory(int iconRes, int textRes) {
+ mIconRes = iconRes;
+ mTextRes = textRes;
+ }
+
+ protected abstract boolean isAvailable(BaseDraggingActivity activity, int displayId);
+ protected abstract ActivityOptions makeLaunchOptions(Activity activity);
+ protected abstract boolean onActivityStarted(BaseDraggingActivity activity);
+
+ @Override
+ public SystemShortcut getShortcut(BaseDraggingActivity activity, TaskView taskView) {
+ final Task task = taskView.getTask();
+ if (!task.isDockable) {
+ return null;
+ }
+ if (!isAvailable(activity, task.key.displayId)) {
+ return null;
+ }
+ return new MultiWindowSystemShortcut(mIconRes, mTextRes, activity, taskView, this);
+ }
+ }
+
+ class MultiWindowSystemShortcut extends SystemShortcut {
+
+ private Handler mHandler;
+
+ private final RecentsView mRecentsView;
+ private final TaskThumbnailView mThumbnailView;
+ private final TaskView mTaskView;
+ private final MultiWindowFactory mFactory;
+
+ public MultiWindowSystemShortcut(int iconRes, int textRes,
+ BaseDraggingActivity activity, TaskView taskView, MultiWindowFactory factory) {
+ super(iconRes, textRes, activity, dummyInfo(taskView));
+
+ mHandler = new Handler(Looper.getMainLooper());
+ mTaskView = taskView;
+ mRecentsView = activity.getOverviewPanel();
+ mThumbnailView = taskView.getThumbnail();
+ mFactory = factory;
+ }
+
+ @Override
+ public void onClick(View view) {
+ Task.TaskKey taskKey = mTaskView.getTask().key;
+ final int taskId = taskKey.id;
+
+ final View.OnLayoutChangeListener onLayoutChangeListener =
+ new View.OnLayoutChangeListener() {
+ @Override
+ public void onLayoutChange(View v, int l, int t, int r, int b,
+ int oldL, int oldT, int oldR, int oldB) {
+ mTaskView.getRootView().removeOnLayoutChangeListener(this);
+ mRecentsView.clearIgnoreResetTask(taskId);
+
+ // Start animating in the side pages once launcher has been resized
+ mRecentsView.dismissTask(mTaskView, false, false);
+ }
+ };
+
+ final DeviceProfile.OnDeviceProfileChangeListener onDeviceProfileChangeListener =
+ new DeviceProfile.OnDeviceProfileChangeListener() {
+ @Override
+ public void onDeviceProfileChanged(DeviceProfile dp) {
+ mTarget.removeOnDeviceProfileChangeListener(this);
+ if (dp.isMultiWindowMode) {
+ mTaskView.getRootView().addOnLayoutChangeListener(
+ onLayoutChangeListener);
+ }
+ }
+ };
+
+ dismissTaskMenuView(mTarget);
+
+ ActivityOptions options = mFactory.makeLaunchOptions(mTarget);
+ if (options != null
+ && ActivityManagerWrapper.getInstance().startActivityFromRecents(taskId,
+ options)) {
+ if (!mFactory.onActivityStarted(mTarget)) {
+ return;
+ }
+ // Add a device profile change listener to kick off animating the side tasks
+ // once we enter multiwindow mode and relayout
+ mTarget.addOnDeviceProfileChangeListener(onDeviceProfileChangeListener);
+
+ final Runnable animStartedListener = () -> {
+ // Hide the task view and wait for the window to be resized
+ // TODO: Consider animating in launcher and do an in-place start activity
+ // afterwards
+ mRecentsView.setIgnoreResetTask(taskId);
+ mTaskView.setAlpha(0f);
+ };
+
+ final int[] position = new int[2];
+ mThumbnailView.getLocationOnScreen(position);
+ final int width = (int) (mThumbnailView.getWidth() * mTaskView.getScaleX());
+ final int height = (int) (mThumbnailView.getHeight() * mTaskView.getScaleY());
+ final Rect taskBounds = new Rect(position[0], position[1],
+ position[0] + width, position[1] + height);
+
+ // Take the thumbnail of the task without a scrim and apply it back after
+ float alpha = mThumbnailView.getDimAlpha();
+ mThumbnailView.setDimAlpha(0);
+ Bitmap thumbnail = RecentsTransition.drawViewIntoHardwareBitmap(
+ taskBounds.width(), taskBounds.height(), mThumbnailView, 1f,
+ Color.BLACK);
+ mThumbnailView.setDimAlpha(alpha);
+
+ AppTransitionAnimationSpecsFuture future =
+ new AppTransitionAnimationSpecsFuture(mHandler) {
+ @Override
+ public List<AppTransitionAnimationSpecCompat> composeSpecs() {
+ return Collections.singletonList(new AppTransitionAnimationSpecCompat(
+ taskId, thumbnail, taskBounds));
+ }
+ };
+ WindowManagerWrapper.getInstance().overridePendingAppTransitionMultiThumbFuture(
+ future, animStartedListener, mHandler, true /* scaleUp */,
+ taskKey.displayId);
+ }
+ }
+ }
+
+ TaskShortcutFactory SPLIT_SCREEN = new MultiWindowFactory(
+ R.drawable.ic_split_screen, R.string.recent_task_option_split_screen) {
+
+ @Override
+ protected boolean isAvailable(BaseDraggingActivity activity, int displayId) {
+ // Don't show menu-item if already in multi-window and the task is from
+ // the secondary display.
+ // TODO(b/118266305): Temporarily disable splitscreen for secondary display while new
+ // implementation is enabled
+ return !activity.getDeviceProfile().isMultiWindowMode
+ && (displayId == -1 || displayId == DEFAULT_DISPLAY);
+ }
+
+ @Override
+ protected ActivityOptions makeLaunchOptions(Activity activity) {
+ final ActivityCompat act = new ActivityCompat(activity);
+ final int navBarPosition = WindowManagerWrapper.getInstance().getNavBarPosition(
+ act.getDisplayId());
+ if (navBarPosition == WindowManagerWrapper.NAV_BAR_POS_INVALID) {
+ return null;
+ }
+ boolean dockTopOrLeft = navBarPosition != WindowManagerWrapper.NAV_BAR_POS_LEFT;
+ return ActivityOptionsCompat.makeSplitScreenOptions(dockTopOrLeft);
+ }
+
+ @Override
+ protected boolean onActivityStarted(BaseDraggingActivity activity) {
+ SystemUiProxy.INSTANCE.get(activity).onSplitScreenInvoked();
+ activity.getUserEventDispatcher().logActionOnControl(TAP,
+ LauncherLogProto.ControlType.SPLIT_SCREEN_TARGET);
+ return true;
+ }
+ };
+
+ TaskShortcutFactory FREE_FORM = new MultiWindowFactory(
+ R.drawable.ic_split_screen, R.string.recent_task_option_freeform) {
+
+ @Override
+ protected boolean isAvailable(BaseDraggingActivity activity, int displayId) {
+ return ActivityManagerWrapper.getInstance().supportsFreeformMultiWindow(activity);
+ }
+
+ @Override
+ protected ActivityOptions makeLaunchOptions(Activity activity) {
+ ActivityOptions activityOptions = ActivityOptionsCompat.makeFreeformOptions();
+ // Arbitrary bounds only because freeform is in dev mode right now
+ Rect r = new Rect(50, 50, 200, 200);
+ activityOptions.setLaunchBounds(r);
+ return activityOptions;
+ }
+
+ @Override
+ protected boolean onActivityStarted(BaseDraggingActivity activity) {
+ activity.returnToHomescreen();
+ return true;
+ }
+ };
+
+ TaskShortcutFactory PIN = (activity, tv) -> {
+ if (!SystemUiProxy.INSTANCE.get(activity).isActive()) {
+ return null;
+ }
+ if (!ActivityManagerWrapper.getInstance().isScreenPinningEnabled()) {
+ return null;
+ }
+ if (ActivityManagerWrapper.getInstance().isLockToAppActive()) {
+ // We shouldn't be able to pin while an app is locked.
+ return null;
+ }
+ return new PinSystemShortcut(activity, tv);
+ };
+
+ class PinSystemShortcut extends SystemShortcut {
+
+ private static final String TAG = "PinSystemShortcut";
+
+ private final TaskView mTaskView;
+
+ public PinSystemShortcut(BaseDraggingActivity target, TaskView tv) {
+ super(R.drawable.ic_pin, R.string.recent_task_option_pin, target, dummyInfo(tv));
+ mTaskView = tv;
+ }
+
+ @Override
+ public void onClick(View view) {
+ Consumer<Boolean> resultCallback = success -> {
+ if (success) {
+ SystemUiProxy.INSTANCE.get(mTarget).startScreenPinning(
+ mTaskView.getTask().key.id);
+ } else {
+ mTaskView.notifyTaskLaunchFailed(TAG);
+ }
+ };
+ mTaskView.launchTask(true, resultCallback, Executors.MAIN_EXECUTOR.getHandler());
+ dismissTaskMenuView(mTarget);
+ }
+ }
+
+ TaskShortcutFactory INSTALL = (activity, view) ->
+ InstantAppResolver.newInstance(activity).isInstantApp(activity,
+ view.getTask().getTopComponent().getPackageName())
+ ? new SystemShortcut.Install(activity, dummyInfo(view)) : null;
+
+}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskSystemShortcut.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskSystemShortcut.java
deleted file mode 100644
index 5a2e3ff..0000000
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskSystemShortcut.java
+++ /dev/null
@@ -1,327 +0,0 @@
-/*
- * Copyright (C) 2018 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 static android.view.Display.DEFAULT_DISPLAY;
-import static com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch.TAP;
-
-import android.app.Activity;
-import android.app.ActivityOptions;
-import android.content.ComponentName;
-import android.content.Intent;
-import android.graphics.Bitmap;
-import android.graphics.Color;
-import android.graphics.Rect;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.UserHandle;
-import android.view.View;
-
-import com.android.launcher3.BaseDraggingActivity;
-import com.android.launcher3.DeviceProfile;
-import com.android.launcher3.ItemInfo;
-import com.android.launcher3.R;
-import com.android.launcher3.WorkspaceItemInfo;
-import com.android.launcher3.popup.SystemShortcut;
-import com.android.launcher3.userevent.nano.LauncherLogProto;
-import com.android.launcher3.util.InstantAppResolver;
-import com.android.quickstep.views.RecentsView;
-import com.android.quickstep.views.TaskThumbnailView;
-import com.android.quickstep.views.TaskView;
-import com.android.systemui.shared.recents.model.Task;
-import com.android.systemui.shared.recents.view.AppTransitionAnimationSpecCompat;
-import com.android.systemui.shared.recents.view.AppTransitionAnimationSpecsFuture;
-import com.android.systemui.shared.recents.view.RecentsTransition;
-import com.android.systemui.shared.system.ActivityCompat;
-import com.android.systemui.shared.system.ActivityManagerWrapper;
-import com.android.systemui.shared.system.ActivityOptionsCompat;
-import com.android.systemui.shared.system.WindowManagerWrapper;
-
-import java.util.Collections;
-import java.util.List;
-import java.util.function.Consumer;
-
-/**
- * Represents a system shortcut that can be shown for a recent task.
- */
-public class TaskSystemShortcut<T extends SystemShortcut> extends SystemShortcut {
-
- private static final String TAG = "TaskSystemShortcut";
-
- protected T mSystemShortcut;
-
- public TaskSystemShortcut(T systemShortcut) {
- super(systemShortcut);
- mSystemShortcut = systemShortcut;
- }
-
- protected TaskSystemShortcut(int iconResId, int labelResId) {
- super(iconResId, labelResId);
- }
-
- @Override
- public View.OnClickListener getOnClickListener(
- BaseDraggingActivity activity, ItemInfo itemInfo) {
- return null;
- }
-
- public View.OnClickListener getOnClickListener(BaseDraggingActivity activity, TaskView view) {
- Task task = view.getTask();
-
- WorkspaceItemInfo dummyInfo = new WorkspaceItemInfo();
- dummyInfo.intent = new Intent();
- ComponentName component = task.getTopComponent();
- dummyInfo.intent.setComponent(component);
- dummyInfo.user = UserHandle.of(task.key.userId);
- dummyInfo.title = TaskUtils.getTitle(activity, task);
-
- return getOnClickListenerForTask(activity, task, dummyInfo);
- }
-
- protected View.OnClickListener getOnClickListenerForTask(
- BaseDraggingActivity activity, Task task, ItemInfo dummyInfo) {
- return mSystemShortcut.getOnClickListener(activity, dummyInfo);
- }
-
- public static class AppInfo extends TaskSystemShortcut<SystemShortcut.AppInfo> {
- public AppInfo() {
- super(new SystemShortcut.AppInfo());
- }
- }
-
- public static abstract class MultiWindow extends TaskSystemShortcut {
-
- private Handler mHandler;
-
- public MultiWindow(int iconRes, int textRes) {
- super(iconRes, textRes);
- mHandler = new Handler(Looper.getMainLooper());
- }
-
- protected abstract boolean isAvailable(BaseDraggingActivity activity, int displayId);
- protected abstract ActivityOptions makeLaunchOptions(Activity activity);
- protected abstract boolean onActivityStarted(BaseDraggingActivity activity);
-
- @Override
- public View.OnClickListener getOnClickListener(
- BaseDraggingActivity activity, TaskView taskView) {
- final Task task = taskView.getTask();
- final int taskId = task.key.id;
- final int displayId = task.key.displayId;
- if (!task.isDockable) {
- return null;
- }
- if (!isAvailable(activity, displayId)) {
- return null;
- }
- final RecentsView recentsView = activity.getOverviewPanel();
-
- final TaskThumbnailView thumbnailView = taskView.getThumbnail();
- return (v -> {
- final View.OnLayoutChangeListener onLayoutChangeListener =
- new View.OnLayoutChangeListener() {
- @Override
- public void onLayoutChange(View v, int l, int t, int r, int b,
- int oldL, int oldT, int oldR, int oldB) {
- taskView.getRootView().removeOnLayoutChangeListener(this);
- recentsView.clearIgnoreResetTask(taskId);
-
- // Start animating in the side pages once launcher has been resized
- recentsView.dismissTask(taskView, false, false);
- }
- };
-
- final DeviceProfile.OnDeviceProfileChangeListener onDeviceProfileChangeListener =
- new DeviceProfile.OnDeviceProfileChangeListener() {
- @Override
- public void onDeviceProfileChanged(DeviceProfile dp) {
- activity.removeOnDeviceProfileChangeListener(this);
- if (dp.isMultiWindowMode) {
- taskView.getRootView().addOnLayoutChangeListener(
- onLayoutChangeListener);
- }
- }
- };
-
- dismissTaskMenuView(activity);
-
- ActivityOptions options = makeLaunchOptions(activity);
- if (options != null
- && ActivityManagerWrapper.getInstance().startActivityFromRecents(taskId,
- options)) {
- if (!onActivityStarted(activity)) {
- return;
- }
- // Add a device profile change listener to kick off animating the side tasks
- // once we enter multiwindow mode and relayout
- activity.addOnDeviceProfileChangeListener(onDeviceProfileChangeListener);
-
- final Runnable animStartedListener = () -> {
- // Hide the task view and wait for the window to be resized
- // TODO: Consider animating in launcher and do an in-place start activity
- // afterwards
- recentsView.setIgnoreResetTask(taskId);
- taskView.setAlpha(0f);
- };
-
- final int[] position = new int[2];
- thumbnailView.getLocationOnScreen(position);
- final int width = (int) (thumbnailView.getWidth() * taskView.getScaleX());
- final int height = (int) (thumbnailView.getHeight() * taskView.getScaleY());
- final Rect taskBounds = new Rect(position[0], position[1],
- position[0] + width, position[1] + height);
-
- // Take the thumbnail of the task without a scrim and apply it back after
- float alpha = thumbnailView.getDimAlpha();
- thumbnailView.setDimAlpha(0);
- Bitmap thumbnail = RecentsTransition.drawViewIntoHardwareBitmap(
- taskBounds.width(), taskBounds.height(), thumbnailView, 1f,
- Color.BLACK);
- thumbnailView.setDimAlpha(alpha);
-
- AppTransitionAnimationSpecsFuture future =
- new AppTransitionAnimationSpecsFuture(mHandler) {
- @Override
- public List<AppTransitionAnimationSpecCompat> composeSpecs() {
- return Collections.singletonList(new AppTransitionAnimationSpecCompat(
- taskId, thumbnail, taskBounds));
- }
- };
- WindowManagerWrapper.getInstance().overridePendingAppTransitionMultiThumbFuture(
- future, animStartedListener, mHandler, true /* scaleUp */, displayId);
- }
- });
- }
- }
-
- public static class SplitScreen extends MultiWindow {
- public SplitScreen() {
- super(R.drawable.ic_split_screen, R.string.recent_task_option_split_screen);
- }
-
- @Override
- protected boolean isAvailable(BaseDraggingActivity activity, int displayId) {
- // Don't show menu-item if already in multi-window and the task is from
- // the secondary display.
- // TODO(b/118266305): Temporarily disable splitscreen for secondary display while new
- // implementation is enabled
- return !activity.getDeviceProfile().isMultiWindowMode
- && (displayId == -1 || displayId == DEFAULT_DISPLAY);
- }
-
- @Override
- protected ActivityOptions makeLaunchOptions(Activity activity) {
- final ActivityCompat act = new ActivityCompat(activity);
- final int navBarPosition = WindowManagerWrapper.getInstance().getNavBarPosition(
- act.getDisplayId());
- if (navBarPosition == WindowManagerWrapper.NAV_BAR_POS_INVALID) {
- return null;
- }
- boolean dockTopOrLeft = navBarPosition != WindowManagerWrapper.NAV_BAR_POS_LEFT;
- return ActivityOptionsCompat.makeSplitScreenOptions(dockTopOrLeft);
- }
-
- @Override
- protected boolean onActivityStarted(BaseDraggingActivity activity) {
- SystemUiProxy.INSTANCE.get(activity).onSplitScreenInvoked();
- activity.getUserEventDispatcher().logActionOnControl(TAP,
- LauncherLogProto.ControlType.SPLIT_SCREEN_TARGET);
- return true;
- }
- }
-
- public static class Freeform extends MultiWindow {
- public Freeform() {
- super(R.drawable.ic_split_screen, R.string.recent_task_option_freeform);
- }
-
- @Override
- protected boolean isAvailable(BaseDraggingActivity activity, int displayId) {
- return ActivityManagerWrapper.getInstance().supportsFreeformMultiWindow(activity);
- }
-
- @Override
- protected ActivityOptions makeLaunchOptions(Activity activity) {
- ActivityOptions activityOptions = ActivityOptionsCompat.makeFreeformOptions();
- // Arbitrary bounds only because freeform is in dev mode right now
- Rect r = new Rect(50, 50, 200, 200);
- activityOptions.setLaunchBounds(r);
- return activityOptions;
- }
-
- @Override
- protected boolean onActivityStarted(BaseDraggingActivity activity) {
- activity.returnToHomescreen();
- return true;
- }
- }
-
- public static class Pin extends TaskSystemShortcut {
-
- private static final String TAG = Pin.class.getSimpleName();
-
- private Handler mHandler;
-
- public Pin() {
- super(R.drawable.ic_pin, R.string.recent_task_option_pin);
- mHandler = new Handler(Looper.getMainLooper());
- }
-
- @Override
- public View.OnClickListener getOnClickListener(
- BaseDraggingActivity activity, TaskView taskView) {
- if (!SystemUiProxy.INSTANCE.get(activity).isActive()) {
- return null;
- }
- if (!ActivityManagerWrapper.getInstance().isScreenPinningEnabled()) {
- return null;
- }
- if (ActivityManagerWrapper.getInstance().isLockToAppActive()) {
- // We shouldn't be able to pin while an app is locked.
- return null;
- }
- return view -> {
- Consumer<Boolean> resultCallback = success -> {
- if (success) {
- SystemUiProxy.INSTANCE.get(activity).startScreenPinning(
- taskView.getTask().key.id);
- } else {
- taskView.notifyTaskLaunchFailed(TAG);
- }
- };
- taskView.launchTask(true, resultCallback, mHandler);
- dismissTaskMenuView(activity);
- };
- }
- }
-
- public static class Install extends TaskSystemShortcut<SystemShortcut.Install> {
- public Install() {
- super(new SystemShortcut.Install());
- }
-
- @Override
- protected View.OnClickListener getOnClickListenerForTask(
- BaseDraggingActivity activity, Task task, ItemInfo itemInfo) {
- if (InstantAppResolver.newInstance(activity).isInstantApp(activity,
- task.getTopComponent().getPackageName())) {
- return mSystemShortcut.createOnClickListener(activity, itemInfo);
- }
- return null;
- }
- }
-}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskMenuView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskMenuView.java
index 07d0796..b810c4a 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskMenuView.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskMenuView.java
@@ -16,7 +16,6 @@
package com.android.quickstep.views;
-import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
import static com.android.quickstep.views.TaskThumbnailView.DIM_ALPHA;
import android.animation.Animator;
@@ -26,7 +25,6 @@
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
-import android.util.Log;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
@@ -41,16 +39,13 @@
import com.android.launcher3.anim.AnimationSuccessListener;
import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.anim.RoundedRectRevealOutlineProvider;
-import com.android.launcher3.testing.TestProtocol;
+import com.android.launcher3.popup.SystemShortcut;
import com.android.launcher3.util.Themes;
import com.android.launcher3.views.BaseDragLayer;
import com.android.quickstep.TaskOverlayFactory;
-import com.android.quickstep.TaskSystemShortcut;
import com.android.quickstep.TaskUtils;
import com.android.quickstep.views.IconView.OnScaleUpdateListener;
-import java.util.List;
-
/**
* Contains options for a recent task when long-pressing its icon.
*/
@@ -197,22 +192,16 @@
params.topMargin = (int) -mThumbnailTopMargin;
mTaskIcon.setLayoutParams(params);
- final BaseDraggingActivity activity = BaseDraggingActivity.fromContext(getContext());
- final List<TaskSystemShortcut> shortcuts =
- TaskOverlayFactory.INSTANCE.get(getContext()).getEnabledShortcuts(taskView);
- final int count = shortcuts.size();
- for (int i = 0; i < count; ++i) {
- final TaskSystemShortcut menuOption = shortcuts.get(i);
- addMenuOption(menuOption, menuOption.getOnClickListener(activity, taskView));
- }
+ TaskOverlayFactory.INSTANCE.get(getContext()).getEnabledShortcuts(taskView)
+ .forEach(this::addMenuOption);
}
- private void addMenuOption(TaskSystemShortcut menuOption, OnClickListener onClickListener) {
+ private void addMenuOption(SystemShortcut menuOption) {
ViewGroup menuOptionView = (ViewGroup) mActivity.getLayoutInflater().inflate(
R.layout.task_view_menu_option, this, false);
menuOption.setIconAndLabelFor(
menuOptionView.findViewById(R.id.icon), menuOptionView.findViewById(R.id.text));
- menuOptionView.setOnClickListener(onClickListener);
+ menuOptionView.setOnClickListener(menuOption);
mOptionLayout.addView(menuOptionView);
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java
index bfb9613..3af0f70 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java
@@ -53,6 +53,7 @@
import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.logging.UserEventDispatcher;
+import com.android.launcher3.popup.SystemShortcut;
import com.android.launcher3.userevent.nano.LauncherLogProto;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
@@ -61,7 +62,6 @@
import com.android.quickstep.RecentsModel;
import com.android.quickstep.TaskIconCache;
import com.android.quickstep.TaskOverlayFactory;
-import com.android.quickstep.TaskSystemShortcut;
import com.android.quickstep.TaskThumbnailCache;
import com.android.quickstep.TaskUtils;
import com.android.quickstep.util.TaskCornerRadius;
@@ -713,15 +713,9 @@
getContext().getText(R.string.accessibility_close_task)));
final Context context = getContext();
- final List<TaskSystemShortcut> shortcuts =
- TaskOverlayFactory.INSTANCE.get(getContext()).getEnabledShortcuts(this);
- final int count = shortcuts.size();
- for (int i = 0; i < count; ++i) {
- final TaskSystemShortcut menuOption = shortcuts.get(i);
- OnClickListener onClickListener = menuOption.getOnClickListener(mActivity, this);
- if (onClickListener != null) {
- info.addAction(menuOption.createAccessibilityAction(context));
- }
+ for (SystemShortcut s : TaskOverlayFactory.INSTANCE.get(getContext())
+ .getEnabledShortcuts(this)) {
+ info.addAction(s.createAccessibilityAction(context));
}
if (mDigitalWellBeingToast.hasLimit()) {
@@ -752,16 +746,10 @@
return true;
}
- final List<TaskSystemShortcut> shortcuts =
- TaskOverlayFactory.INSTANCE.get(getContext()).getEnabledShortcuts(this);
- final int count = shortcuts.size();
- for (int i = 0; i < count; ++i) {
- final TaskSystemShortcut menuOption = shortcuts.get(i);
- if (menuOption.hasHandlerForAction(action)) {
- OnClickListener onClickListener = menuOption.getOnClickListener(mActivity, this);
- if (onClickListener != null) {
- onClickListener.onClick(this);
- }
+ for (SystemShortcut s : TaskOverlayFactory.INSTANCE.get(getContext())
+ .getEnabledShortcuts(this)) {
+ if (s.hasHandlerForAction(action)) {
+ s.onClick(this);
return true;
}
}
diff --git a/src/com/android/launcher3/popup/PopupContainerWithArrow.java b/src/com/android/launcher3/popup/PopupContainerWithArrow.java
index 4833c26..8e5d852 100644
--- a/src/com/android/launcher3/popup/PopupContainerWithArrow.java
+++ b/src/com/android/launcher3/popup/PopupContainerWithArrow.java
@@ -382,8 +382,7 @@
@Override
public void onWidgetsBound() {
ItemInfo itemInfo = (ItemInfo) mOriginalIcon.getTag();
- SystemShortcut widgetInfo = new SystemShortcut.Widgets();
- View.OnClickListener onClickListener = widgetInfo.getOnClickListener(mLauncher, itemInfo);
+ SystemShortcut widgetInfo = SystemShortcut.WIDGETS.getShortcut(mLauncher, itemInfo);
View widgetsView = null;
int count = mSystemShortcutContainer.getChildCount();
for (int i = 0; i < count; i++) {
@@ -394,7 +393,7 @@
}
}
- if (onClickListener != null && widgetsView == null) {
+ if (widgetInfo != null && widgetsView == null) {
// We didn't have any widgets cached but now there are some, so enable the shortcut.
if (mSystemShortcutContainer != this) {
initializeSystemShortcut(
@@ -407,7 +406,7 @@
close(false);
PopupContainerWithArrow.showForIcon(mOriginalIcon);
}
- } else if (onClickListener == null && widgetsView != null) {
+ } else if (widgetInfo == null && widgetsView != null) {
// No widgets exist, but we previously added the shortcut so remove it.
if (mSystemShortcutContainer != this) {
mSystemShortcutContainer.removeView(widgetsView);
@@ -430,8 +429,7 @@
info.setIconAndContentDescriptionFor((ImageView) view);
}
view.setTag(info);
- view.setOnClickListener(info.getOnClickListener(mLauncher,
- (ItemInfo) mOriginalIcon.getTag()));
+ view.setOnClickListener(info);
}
/**
diff --git a/src/com/android/launcher3/popup/RemoteActionShortcut.java b/src/com/android/launcher3/popup/RemoteActionShortcut.java
index 5a5fbab..8751202 100644
--- a/src/com/android/launcher3/popup/RemoteActionShortcut.java
+++ b/src/com/android/launcher3/popup/RemoteActionShortcut.java
@@ -16,13 +16,19 @@
package com.android.launcher3.popup;
+import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
+
+import android.annotation.TargetApi;
import android.app.PendingIntent;
import android.app.RemoteAction;
+import android.content.Context;
import android.content.Intent;
-import android.os.Handler;
-import android.os.Looper;
+import android.os.Build;
import android.util.Log;
import android.view.View;
+import android.view.accessibility.AccessibilityNodeInfo;
+import android.widget.ImageView;
+import android.widget.TextView;
import android.widget.Toast;
import com.android.launcher3.AbstractFloatingView;
@@ -32,55 +38,75 @@
import com.android.launcher3.Utilities;
import com.android.launcher3.userevent.nano.LauncherLogProto;
+@TargetApi(Build.VERSION_CODES.Q)
public class RemoteActionShortcut extends SystemShortcut<BaseDraggingActivity> {
private static final String TAG = "RemoteActionShortcut";
private static final boolean DEBUG = Utilities.IS_DEBUG_DEVICE;
private final RemoteAction mAction;
- public RemoteActionShortcut(RemoteAction action) {
- super(action.getIcon(), action.getTitle(), action.getContentDescription(),
- R.id.action_remote_action_shortcut);
+ public RemoteActionShortcut(RemoteAction action,
+ BaseDraggingActivity activity, ItemInfo itemInfo) {
+ super(0, R.id.action_remote_action_shortcut, activity, itemInfo);
mAction = action;
}
@Override
- public View.OnClickListener getOnClickListener(
- final BaseDraggingActivity activity, final ItemInfo itemInfo) {
- return view -> {
- AbstractFloatingView.closeAllOpenViews(activity);
+ public void setIconAndLabelFor(View iconView, TextView labelView) {
+ mAction.getIcon().loadDrawableAsync(iconView.getContext(),
+ iconView::setBackground,
+ MAIN_EXECUTOR.getHandler());
+ labelView.setText(mAction.getTitle());
+ }
- final String actionIdentity = mAction.getTitle() + ", " +
- itemInfo.getTargetComponent().getPackageName();
- try {
- if (DEBUG) Log.d(TAG, "Sending action: " + actionIdentity);
- mAction.getActionIntent().send(
- activity,
- 0,
- new Intent().putExtra(
- Intent.EXTRA_PACKAGE_NAME,
- itemInfo.getTargetComponent().getPackageName()),
- (pendingIntent, intent, resultCode, resultData, resultExtras) -> {
- if (DEBUG) Log.d(TAG, "Action is complete: " + actionIdentity);
- if (resultData != null && !resultData.isEmpty()) {
- Log.e(TAG, "Remote action returned result: " + actionIdentity
- + " : " + resultData);
- Toast.makeText(activity, resultData, Toast.LENGTH_SHORT).show();
- }
- },
- new Handler(Looper.getMainLooper()));
- } catch (PendingIntent.CanceledException e) {
- Log.e(TAG, "Remote action canceled: " + actionIdentity, e);
- Toast.makeText(activity, activity.getString(
- R.string.remote_action_failed,
- mAction.getTitle()),
- Toast.LENGTH_SHORT)
- .show();
- }
+ @Override
+ public void setIconAndContentDescriptionFor(ImageView view) {
+ mAction.getIcon().loadDrawableAsync(view.getContext(),
+ view::setImageDrawable,
+ MAIN_EXECUTOR.getHandler());
+ view.setContentDescription(mAction.getContentDescription());
+ }
- activity.getUserEventDispatcher().logActionOnControl(LauncherLogProto.Action.Touch.TAP,
- LauncherLogProto.ControlType.REMOTE_ACTION_SHORTCUT, view);
- };
+ @Override
+ public AccessibilityNodeInfo.AccessibilityAction createAccessibilityAction(Context context) {
+ return new AccessibilityNodeInfo.AccessibilityAction(
+ R.id.action_remote_action_shortcut, mAction.getContentDescription());
+ }
+
+ @Override
+ public void onClick(View view) {
+ AbstractFloatingView.closeAllOpenViews(mTarget);
+
+ final String actionIdentity = mAction.getTitle() + ", "
+ + mItemInfo.getTargetComponent().getPackageName();
+ try {
+ if (DEBUG) Log.d(TAG, "Sending action: " + actionIdentity);
+ mAction.getActionIntent().send(
+ mTarget,
+ 0,
+ new Intent().putExtra(
+ Intent.EXTRA_PACKAGE_NAME,
+ mItemInfo.getTargetComponent().getPackageName()),
+ (pendingIntent, intent, resultCode, resultData, resultExtras) -> {
+ if (DEBUG) Log.d(TAG, "Action is complete: " + actionIdentity);
+ if (resultData != null && !resultData.isEmpty()) {
+ Log.e(TAG, "Remote action returned result: " + actionIdentity
+ + " : " + resultData);
+ Toast.makeText(mTarget, resultData, Toast.LENGTH_SHORT).show();
+ }
+ },
+ MAIN_EXECUTOR.getHandler());
+ } catch (PendingIntent.CanceledException e) {
+ Log.e(TAG, "Remote action canceled: " + actionIdentity, e);
+ Toast.makeText(mTarget, mTarget.getString(
+ R.string.remote_action_failed,
+ mAction.getTitle()),
+ Toast.LENGTH_SHORT)
+ .show();
+ }
+
+ mTarget.getUserEventDispatcher().logActionOnControl(LauncherLogProto.Action.Touch.TAP,
+ LauncherLogProto.ControlType.REMOTE_ACTION_SHORTCUT, view);
}
@Override
diff --git a/src/com/android/launcher3/popup/SystemShortcut.java b/src/com/android/launcher3/popup/SystemShortcut.java
index a87b7b8..222c6c9 100644
--- a/src/com/android/launcher3/popup/SystemShortcut.java
+++ b/src/com/android/launcher3/popup/SystemShortcut.java
@@ -5,14 +5,13 @@
import android.content.Context;
import android.content.Intent;
import android.graphics.Rect;
-import android.graphics.drawable.Icon;
-import android.os.Handler;
-import android.os.Looper;
import android.view.View;
import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.ImageView;
import android.widget.TextView;
+import androidx.annotation.Nullable;
+
import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.ItemInfo;
@@ -39,41 +38,30 @@
* Example system shortcuts, defined as inner classes, include Widgets and AppInfo.
* @param <T>
*/
-public abstract class SystemShortcut<T extends BaseDraggingActivity>
- extends ItemInfo {
+public abstract class SystemShortcut<T extends BaseDraggingActivity> extends ItemInfo
+ implements View.OnClickListener {
+
private final int mIconResId;
private final int mLabelResId;
- private final Icon mIcon;
- private final CharSequence mLabel;
- private final CharSequence mContentDescription;
private final int mAccessibilityActionId;
- public SystemShortcut(int iconResId, int labelResId) {
+ protected final T mTarget;
+ protected final ItemInfo mItemInfo;
+
+ public SystemShortcut(int iconResId, int labelResId, T target, ItemInfo itemInfo) {
mIconResId = iconResId;
mLabelResId = labelResId;
mAccessibilityActionId = labelResId;
- mIcon = null;
- mLabel = null;
- mContentDescription = null;
+ mTarget = target;
+ mItemInfo = itemInfo;
}
- public SystemShortcut(Icon icon, CharSequence label, CharSequence contentDescription,
- int accessibilityActionId) {
- mIcon = icon;
- mLabel = label;
- mContentDescription = contentDescription;
- mAccessibilityActionId = accessibilityActionId;
- mIconResId = 0;
- mLabelResId = 0;
- }
-
- public SystemShortcut(SystemShortcut other) {
+ public SystemShortcut(SystemShortcut<T> other) {
mIconResId = other.mIconResId;
mLabelResId = other.mLabelResId;
- mIcon = other.mIcon;
- mLabel = other.mLabel;
- mContentDescription = other.mContentDescription;
mAccessibilityActionId = other.mAccessibilityActionId;
+ mTarget = other.mTarget;
+ mItemInfo = other.mItemInfo;
}
/**
@@ -84,150 +72,135 @@
}
public void setIconAndLabelFor(View iconView, TextView labelView) {
- if (mIcon != null) {
- mIcon.loadDrawableAsync(iconView.getContext(),
- iconView::setBackground,
- new Handler(Looper.getMainLooper()));
- } else {
- iconView.setBackgroundResource(mIconResId);
- }
-
- if (mLabel != null) {
- labelView.setText(mLabel);
- } else {
- labelView.setText(mLabelResId);
- }
+ iconView.setBackgroundResource(mIconResId);
+ labelView.setText(mLabelResId);
}
public void setIconAndContentDescriptionFor(ImageView view) {
- if (mIcon != null) {
- mIcon.loadDrawableAsync(view.getContext(),
- view::setImageDrawable,
- new Handler(Looper.getMainLooper()));
- } else {
- view.setImageResource(mIconResId);
- }
-
- view.setContentDescription(getContentDescription(view.getContext()));
- }
-
- private CharSequence getContentDescription(Context context) {
- return mContentDescription != null ? mContentDescription : context.getText(mLabelResId);
+ view.setImageResource(mIconResId);
+ view.setContentDescription(view.getContext().getText(mLabelResId));
}
public AccessibilityNodeInfo.AccessibilityAction createAccessibilityAction(Context context) {
- return new AccessibilityNodeInfo.AccessibilityAction(mAccessibilityActionId,
- getContentDescription(context));
+ return new AccessibilityNodeInfo.AccessibilityAction(
+ mAccessibilityActionId, context.getText(mLabelResId));
}
public boolean hasHandlerForAction(int action) {
return mAccessibilityActionId == action;
}
- public abstract View.OnClickListener getOnClickListener(T activity, ItemInfo itemInfo);
+ public interface Factory<T extends BaseDraggingActivity> {
+
+ @Nullable SystemShortcut<T> getShortcut(T activity, ItemInfo itemInfo);
+ }
+
+ public static final Factory<Launcher> WIDGETS = (launcher, itemInfo) -> {
+ if (itemInfo.getTargetComponent() == null) return null;
+ final List<WidgetItem> widgets =
+ launcher.getPopupDataProvider().getWidgetsForPackageUser(new PackageUserKey(
+ itemInfo.getTargetComponent().getPackageName(), itemInfo.user));
+ if (widgets == null) {
+ return null;
+ }
+ return new Widgets(launcher, itemInfo);
+ };
public static class Widgets extends SystemShortcut<Launcher> {
- public Widgets() {
- super(R.drawable.ic_widget, R.string.widget_button_text);
+ public Widgets(Launcher target, ItemInfo itemInfo) {
+ super(R.drawable.ic_widget, R.string.widget_button_text, target, itemInfo);
}
@Override
- public View.OnClickListener getOnClickListener(final Launcher launcher,
- final ItemInfo itemInfo) {
- if (itemInfo.getTargetComponent() == null) return null;
- final List<WidgetItem> widgets =
- launcher.getPopupDataProvider().getWidgetsForPackageUser(new PackageUserKey(
- itemInfo.getTargetComponent().getPackageName(), itemInfo.user));
- if (widgets == null) {
- return null;
- }
- return (view) -> {
- AbstractFloatingView.closeAllOpenViews(launcher);
- WidgetsBottomSheet widgetsBottomSheet =
- (WidgetsBottomSheet) launcher.getLayoutInflater().inflate(
- R.layout.widgets_bottom_sheet, launcher.getDragLayer(), false);
- widgetsBottomSheet.populateAndShow(itemInfo);
- launcher.getUserEventDispatcher().logActionOnControl(Action.Touch.TAP,
- ControlType.WIDGETS_BUTTON, view);
- };
+ public void onClick(View view) {
+ AbstractFloatingView.closeAllOpenViews(mTarget);
+ WidgetsBottomSheet widgetsBottomSheet =
+ (WidgetsBottomSheet) mTarget.getLayoutInflater().inflate(
+ R.layout.widgets_bottom_sheet, mTarget.getDragLayer(), false);
+ widgetsBottomSheet.populateAndShow(mItemInfo);
+ mTarget.getUserEventDispatcher().logActionOnControl(Action.Touch.TAP,
+ ControlType.WIDGETS_BUTTON, view);
}
}
+ public static final Factory<BaseDraggingActivity> APP_INFO = AppInfo::new;
+
public static class AppInfo extends SystemShortcut {
- public AppInfo() {
- super(R.drawable.ic_info_no_shadow, R.string.app_info_drop_target_label);
+
+ public AppInfo(BaseDraggingActivity target, ItemInfo itemInfo) {
+ super(R.drawable.ic_info_no_shadow, R.string.app_info_drop_target_label, target,
+ itemInfo);
}
@Override
- public View.OnClickListener getOnClickListener(
- BaseDraggingActivity activity, ItemInfo itemInfo) {
- return (view) -> {
- dismissTaskMenuView(activity);
- Rect sourceBounds = activity.getViewBounds(view);
- new PackageManagerHelper(activity).startDetailsActivityForInfo(
- itemInfo, sourceBounds, ActivityOptions.makeBasic().toBundle());
- activity.getUserEventDispatcher().logActionOnControl(Action.Touch.TAP,
- ControlType.APPINFO_TARGET, view);
- };
+ public void onClick(View view) {
+ dismissTaskMenuView(mTarget);
+ Rect sourceBounds = mTarget.getViewBounds(view);
+ new PackageManagerHelper(mTarget).startDetailsActivityForInfo(
+ mItemInfo, sourceBounds, ActivityOptions.makeBasic().toBundle());
+ mTarget.getUserEventDispatcher().logActionOnControl(Action.Touch.TAP,
+ ControlType.APPINFO_TARGET, view);
}
}
+ public static Factory<BaseDraggingActivity> INSTALL = (activity, itemInfo) -> {
+ boolean supportsWebUI = (itemInfo instanceof WorkspaceItemInfo)
+ && ((WorkspaceItemInfo) itemInfo).hasStatusFlag(
+ WorkspaceItemInfo.FLAG_SUPPORTS_WEB_UI);
+ boolean isInstantApp = false;
+ if (itemInfo instanceof com.android.launcher3.AppInfo) {
+ com.android.launcher3.AppInfo appInfo = (com.android.launcher3.AppInfo) itemInfo;
+ isInstantApp = InstantAppResolver.newInstance(activity).isInstantApp(appInfo);
+ }
+ boolean enabled = supportsWebUI || isInstantApp;
+ if (!enabled) {
+ return null;
+ }
+ return new Install(activity, itemInfo);
+ };
+
public static class Install extends SystemShortcut {
- public Install() {
- super(R.drawable.ic_install_no_shadow, R.string.install_drop_target_label);
+
+ public Install(BaseDraggingActivity target, ItemInfo itemInfo) {
+ super(R.drawable.ic_install_no_shadow, R.string.install_drop_target_label,
+ target, itemInfo);
}
@Override
- public View.OnClickListener getOnClickListener(
- BaseDraggingActivity activity, ItemInfo itemInfo) {
- boolean supportsWebUI = (itemInfo instanceof WorkspaceItemInfo) &&
- ((WorkspaceItemInfo) itemInfo).hasStatusFlag(WorkspaceItemInfo.FLAG_SUPPORTS_WEB_UI);
- boolean isInstantApp = false;
- if (itemInfo instanceof com.android.launcher3.AppInfo) {
- com.android.launcher3.AppInfo appInfo = (com.android.launcher3.AppInfo) itemInfo;
- isInstantApp = InstantAppResolver.newInstance(activity).isInstantApp(appInfo);
- }
- boolean enabled = supportsWebUI || isInstantApp;
- if (!enabled) {
- return null;
- }
- return createOnClickListener(activity, itemInfo);
- }
-
- public View.OnClickListener createOnClickListener(
- BaseDraggingActivity activity, ItemInfo itemInfo) {
- return view -> {
- Intent intent = new PackageManagerHelper(view.getContext()).getMarketIntent(
- itemInfo.getTargetComponent().getPackageName());
- activity.startActivitySafely(view, intent, itemInfo, null);
- AbstractFloatingView.closeAllOpenViews(activity);
- };
+ public void onClick(View view) {
+ Intent intent = new PackageManagerHelper(view.getContext()).getMarketIntent(
+ mItemInfo.getTargetComponent().getPackageName());
+ mTarget.startActivitySafely(view, intent, mItemInfo, null);
+ AbstractFloatingView.closeAllOpenViews(mTarget);
}
}
+ public static Factory<Launcher> DISMISS_PREDICTION = (launcher, itemInfo) -> {
+ if (!FeatureFlags.ENABLE_PREDICTION_DISMISS.get()) return null;
+ if (itemInfo.container != LauncherSettings.Favorites.CONTAINER_PREDICTION) return null;
+ return new DismissPrediction(launcher, itemInfo);
+ };
+
public static class DismissPrediction extends SystemShortcut<Launcher> {
- public DismissPrediction() {
- super(R.drawable.ic_remove_no_shadow, R.string.dismiss_prediction_label);
+ public DismissPrediction(Launcher launcher, ItemInfo itemInfo) {
+ super(R.drawable.ic_remove_no_shadow, R.string.dismiss_prediction_label, launcher,
+ itemInfo);
}
@Override
- public View.OnClickListener getOnClickListener(Launcher activity, ItemInfo itemInfo) {
- if (!FeatureFlags.ENABLE_PREDICTION_DISMISS.get()) return null;
- if (itemInfo.container != LauncherSettings.Favorites.CONTAINER_PREDICTION) return null;
- return (view) -> {
- PopupContainerWithArrow.closeAllOpenViews(activity);
- activity.getUserEventDispatcher().logActionOnControl(Action.Touch.TAP,
- ControlType.DISMISS_PREDICTION, ContainerType.DEEPSHORTCUTS);
- AppLaunchTracker.INSTANCE.get(view.getContext())
- .onDismissApp(itemInfo.getTargetComponent(),
- itemInfo.user,
- AppLaunchTracker.CONTAINER_PREDICTIONS);
- };
+ public void onClick(View view) {
+ PopupContainerWithArrow.closeAllOpenViews(mTarget);
+ mTarget.getUserEventDispatcher().logActionOnControl(Action.Touch.TAP,
+ ControlType.DISMISS_PREDICTION, ContainerType.DEEPSHORTCUTS);
+ AppLaunchTracker.INSTANCE.get(view.getContext()).onDismissApp(
+ mItemInfo.getTargetComponent(),
+ mItemInfo.user,
+ AppLaunchTracker.CONTAINER_PREDICTIONS);
}
}
- protected static void dismissTaskMenuView(BaseDraggingActivity activity) {
+ public static void dismissTaskMenuView(BaseDraggingActivity activity) {
AbstractFloatingView.closeOpenViews(activity, true,
AbstractFloatingView.TYPE_ALL & ~AbstractFloatingView.TYPE_REBIND_SAFE);
}
diff --git a/src/com/android/launcher3/popup/SystemShortcutFactory.java b/src/com/android/launcher3/popup/SystemShortcutFactory.java
index dfcc2f8..8b8a4d0 100644
--- a/src/com/android/launcher3/popup/SystemShortcutFactory.java
+++ b/src/com/android/launcher3/popup/SystemShortcutFactory.java
@@ -34,25 +34,24 @@
forOverride(SystemShortcutFactory.class, R.string.system_shortcut_factory_class);
/** Note that these are in order of priority. */
- private final SystemShortcut[] mAllShortcuts;
+ private final SystemShortcut.Factory[] mAllFactories;
@SuppressWarnings("unused")
public SystemShortcutFactory() {
- this(new SystemShortcut.AppInfo(),
- new SystemShortcut.Widgets(),
- new SystemShortcut.Install(),
- new SystemShortcut.DismissPrediction());
+ this(SystemShortcut.APP_INFO, SystemShortcut.WIDGETS, SystemShortcut.INSTALL,
+ SystemShortcut.DISMISS_PREDICTION);
}
- protected SystemShortcutFactory(SystemShortcut... shortcuts) {
- mAllShortcuts = shortcuts;
+ protected SystemShortcutFactory(SystemShortcut.Factory... factories) {
+ mAllFactories = factories;
}
public @NonNull List<SystemShortcut> getEnabledShortcuts(Launcher launcher, ItemInfo info) {
List<SystemShortcut> systemShortcuts = new ArrayList<>();
- for (SystemShortcut systemShortcut : mAllShortcuts) {
- if (systemShortcut.getOnClickListener(launcher, info) != null) {
- systemShortcuts.add(systemShortcut);
+ for (SystemShortcut.Factory factory : mAllFactories) {
+ SystemShortcut shortcut = factory.getShortcut(launcher, info);
+ if (shortcut != null) {
+ systemShortcuts.add(shortcut);
}
}