Loading quickstep/recents_ui_overrides/src/com/android/quickstep/TaskOverlayFactory.java +13 −14 Original line number Diff line number Diff line Loading @@ -19,11 +19,11 @@ package com.android.quickstep; 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; Loading @@ -40,25 +40,24 @@ import java.util.List; 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; Loading quickstep/recents_ui_overrides/src/com/android/quickstep/TaskSystemShortcut.java→quickstep/recents_ui_overrides/src/com/android/quickstep/TaskShortcutFactory.java +312 −0 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ 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; Loading @@ -33,11 +34,12 @@ 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.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; Loading @@ -58,28 +60,11 @@ 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; } public interface TaskShortcutFactory { protected TaskSystemShortcut(int iconResId, int labelResId) { super(iconResId, labelResId); } SystemShortcut getShortcut(BaseDraggingActivity activity, TaskView view); @Override public View.OnClickListener getOnClickListener( BaseDraggingActivity activity, ItemInfo itemInfo) { return null; } public View.OnClickListener getOnClickListener(BaseDraggingActivity activity, TaskView view) { static WorkspaceItemInfo dummyInfo(TaskView view) { Task task = view.getTask(); WorkspaceItemInfo dummyInfo = new WorkspaceItemInfo(); Loading @@ -87,29 +72,20 @@ public class TaskSystemShortcut<T extends SystemShortcut> extends SystemShortcut 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); dummyInfo.title = TaskUtils.getTitle(view.getContext(), task); return dummyInfo; } protected View.OnClickListener getOnClickListenerForTask( BaseDraggingActivity activity, Task task, ItemInfo dummyInfo) { return mSystemShortcut.getOnClickListener(activity, dummyInfo); } TaskShortcutFactory APP_INFO = (activity, view) -> new AppInfo(activity, dummyInfo(view)); public static class AppInfo extends TaskSystemShortcut<SystemShortcut.AppInfo> { public AppInfo() { super(new SystemShortcut.AppInfo()); } } abstract class MultiWindowFactory implements TaskShortcutFactory { public static abstract class MultiWindow extends TaskSystemShortcut { private final int mIconRes; private final int mTextRes; private Handler mHandler; public MultiWindow(int iconRes, int textRes) { super(iconRes, textRes); mHandler = new Handler(Looper.getMainLooper()); MultiWindowFactory(int iconRes, int textRes) { mIconRes = iconRes; mTextRes = textRes; } protected abstract boolean isAvailable(BaseDraggingActivity activity, int displayId); Loading @@ -117,31 +93,53 @@ public class TaskSystemShortcut<T extends SystemShortcut> extends SystemShortcut protected abstract boolean onActivityStarted(BaseDraggingActivity activity); @Override public View.OnClickListener getOnClickListener( BaseDraggingActivity activity, TaskView taskView) { public SystemShortcut getShortcut(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)) { if (!isAvailable(activity, task.key.displayId)) { return null; } final RecentsView recentsView = activity.getOverviewPanel(); 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 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); mTaskView.getRootView().removeOnLayoutChangeListener(this); mRecentsView.clearIgnoreResetTask(taskId); // Start animating in the side pages once launcher has been resized recentsView.dismissTask(taskView, false, false); mRecentsView.dismissTask(mTaskView, false, false); } }; Loading @@ -149,49 +147,49 @@ public class TaskSystemShortcut<T extends SystemShortcut> extends SystemShortcut new DeviceProfile.OnDeviceProfileChangeListener() { @Override public void onDeviceProfileChanged(DeviceProfile dp) { activity.removeOnDeviceProfileChangeListener(this); mTarget.removeOnDeviceProfileChangeListener(this); if (dp.isMultiWindowMode) { taskView.getRootView().addOnLayoutChangeListener( mTaskView.getRootView().addOnLayoutChangeListener( onLayoutChangeListener); } } }; dismissTaskMenuView(activity); dismissTaskMenuView(mTarget); ActivityOptions options = makeLaunchOptions(activity); ActivityOptions options = mFactory.makeLaunchOptions(mTarget); if (options != null && ActivityManagerWrapper.getInstance().startActivityFromRecents(taskId, options)) { if (!onActivityStarted(activity)) { 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 activity.addOnDeviceProfileChangeListener(onDeviceProfileChangeListener); 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 recentsView.setIgnoreResetTask(taskId); taskView.setAlpha(0f); mRecentsView.setIgnoreResetTask(taskId); mTaskView.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()); 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 = thumbnailView.getDimAlpha(); thumbnailView.setDimAlpha(0); float alpha = mThumbnailView.getDimAlpha(); mThumbnailView.setDimAlpha(0); Bitmap thumbnail = RecentsTransition.drawViewIntoHardwareBitmap( taskBounds.width(), taskBounds.height(), thumbnailView, 1f, taskBounds.width(), taskBounds.height(), mThumbnailView, 1f, Color.BLACK); thumbnailView.setDimAlpha(alpha); mThumbnailView.setDimAlpha(alpha); AppTransitionAnimationSpecsFuture future = new AppTransitionAnimationSpecsFuture(mHandler) { Loading @@ -202,16 +200,14 @@ public class TaskSystemShortcut<T extends SystemShortcut> extends SystemShortcut } }; WindowManagerWrapper.getInstance().overridePendingAppTransitionMultiThumbFuture( future, animStartedListener, mHandler, true /* scaleUp */, displayId); future, animStartedListener, mHandler, true /* scaleUp */, taskKey.displayId); } }); } } public static class SplitScreen extends MultiWindow { public SplitScreen() { super(R.drawable.ic_split_screen, R.string.recent_task_option_split_screen); } 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) { Loading Loading @@ -242,12 +238,10 @@ public class TaskSystemShortcut<T extends SystemShortcut> extends SystemShortcut 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); } TaskShortcutFactory FREE_FORM = new MultiWindowFactory( R.drawable.ic_split_screen, R.string.recent_task_option_freeform) { @Override protected boolean isAvailable(BaseDraggingActivity activity, int displayId) { Loading @@ -268,22 +262,9 @@ public class TaskSystemShortcut<T extends SystemShortcut> extends SystemShortcut 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) { TaskShortcutFactory PIN = (activity, tv) -> { if (!SystemUiProxy.INSTANCE.get(activity).isActive()) { return null; } Loading @@ -294,34 +275,38 @@ public class TaskSystemShortcut<T extends SystemShortcut> extends SystemShortcut // We shouldn't be able to pin while an app is locked. return null; } return view -> { 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(activity).startScreenPinning( taskView.getTask().key.id); SystemUiProxy.INSTANCE.get(mTarget).startScreenPinning( mTaskView.getTask().key.id); } else { taskView.notifyTaskLaunchFailed(TAG); mTaskView.notifyTaskLaunchFailed(TAG); } }; taskView.launchTask(true, resultCallback, mHandler); dismissTaskMenuView(activity); }; mTaskView.launchTask(true, resultCallback, Executors.MAIN_EXECUTOR.getHandler()); dismissTaskMenuView(mTarget); } } public static class Install extends TaskSystemShortcut<SystemShortcut.Install> { public Install() { super(new SystemShortcut.Install()); } TaskShortcutFactory INSTALL = (activity, view) -> InstantAppResolver.newInstance(activity).isInstantApp(activity, view.getTask().getTopComponent().getPackageName()) ? new SystemShortcut.Install(activity, dummyInfo(view)) : null; @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; } } } quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskMenuView.java +5 −16 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -26,7 +25,6 @@ import android.content.Context; 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; Loading @@ -41,16 +39,13 @@ import com.android.launcher3.R; 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. */ Loading Loading @@ -197,22 +192,16 @@ public class TaskMenuView extends AbstractFloatingView { 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); } Loading quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java +8 −20 Original line number Diff line number Diff line Loading @@ -53,6 +53,7 @@ import com.android.launcher3.Utilities; 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; Loading @@ -61,7 +62,6 @@ import com.android.launcher3.util.ViewPool.Reusable; 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; Loading Loading @@ -713,15 +713,9 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable { 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()) { Loading Loading @@ -752,16 +746,10 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable { 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; } } Loading src/com/android/launcher3/popup/PopupContainerWithArrow.java +4 −6 Original line number Diff line number Diff line Loading @@ -382,8 +382,7 @@ public class PopupContainerWithArrow extends ArrowPopup implements DragSource, @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++) { Loading @@ -394,7 +393,7 @@ public class PopupContainerWithArrow extends ArrowPopup implements DragSource, } } 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( Loading @@ -407,7 +406,7 @@ public class PopupContainerWithArrow extends ArrowPopup implements DragSource, 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); Loading @@ -430,8 +429,7 @@ public class PopupContainerWithArrow extends ArrowPopup implements DragSource, info.setIconAndContentDescriptionFor((ImageView) view); } view.setTag(info); view.setOnClickListener(info.getOnClickListener(mLauncher, (ItemInfo) mOriginalIcon.getTag())); view.setOnClickListener(info); } /** Loading Loading
quickstep/recents_ui_overrides/src/com/android/quickstep/TaskOverlayFactory.java +13 −14 Original line number Diff line number Diff line Loading @@ -19,11 +19,11 @@ package com.android.quickstep; 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; Loading @@ -40,25 +40,24 @@ import java.util.List; 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; Loading
quickstep/recents_ui_overrides/src/com/android/quickstep/TaskSystemShortcut.java→quickstep/recents_ui_overrides/src/com/android/quickstep/TaskShortcutFactory.java +312 −0 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ 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; Loading @@ -33,11 +34,12 @@ 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.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; Loading @@ -58,28 +60,11 @@ 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; } public interface TaskShortcutFactory { protected TaskSystemShortcut(int iconResId, int labelResId) { super(iconResId, labelResId); } SystemShortcut getShortcut(BaseDraggingActivity activity, TaskView view); @Override public View.OnClickListener getOnClickListener( BaseDraggingActivity activity, ItemInfo itemInfo) { return null; } public View.OnClickListener getOnClickListener(BaseDraggingActivity activity, TaskView view) { static WorkspaceItemInfo dummyInfo(TaskView view) { Task task = view.getTask(); WorkspaceItemInfo dummyInfo = new WorkspaceItemInfo(); Loading @@ -87,29 +72,20 @@ public class TaskSystemShortcut<T extends SystemShortcut> extends SystemShortcut 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); dummyInfo.title = TaskUtils.getTitle(view.getContext(), task); return dummyInfo; } protected View.OnClickListener getOnClickListenerForTask( BaseDraggingActivity activity, Task task, ItemInfo dummyInfo) { return mSystemShortcut.getOnClickListener(activity, dummyInfo); } TaskShortcutFactory APP_INFO = (activity, view) -> new AppInfo(activity, dummyInfo(view)); public static class AppInfo extends TaskSystemShortcut<SystemShortcut.AppInfo> { public AppInfo() { super(new SystemShortcut.AppInfo()); } } abstract class MultiWindowFactory implements TaskShortcutFactory { public static abstract class MultiWindow extends TaskSystemShortcut { private final int mIconRes; private final int mTextRes; private Handler mHandler; public MultiWindow(int iconRes, int textRes) { super(iconRes, textRes); mHandler = new Handler(Looper.getMainLooper()); MultiWindowFactory(int iconRes, int textRes) { mIconRes = iconRes; mTextRes = textRes; } protected abstract boolean isAvailable(BaseDraggingActivity activity, int displayId); Loading @@ -117,31 +93,53 @@ public class TaskSystemShortcut<T extends SystemShortcut> extends SystemShortcut protected abstract boolean onActivityStarted(BaseDraggingActivity activity); @Override public View.OnClickListener getOnClickListener( BaseDraggingActivity activity, TaskView taskView) { public SystemShortcut getShortcut(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)) { if (!isAvailable(activity, task.key.displayId)) { return null; } final RecentsView recentsView = activity.getOverviewPanel(); 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 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); mTaskView.getRootView().removeOnLayoutChangeListener(this); mRecentsView.clearIgnoreResetTask(taskId); // Start animating in the side pages once launcher has been resized recentsView.dismissTask(taskView, false, false); mRecentsView.dismissTask(mTaskView, false, false); } }; Loading @@ -149,49 +147,49 @@ public class TaskSystemShortcut<T extends SystemShortcut> extends SystemShortcut new DeviceProfile.OnDeviceProfileChangeListener() { @Override public void onDeviceProfileChanged(DeviceProfile dp) { activity.removeOnDeviceProfileChangeListener(this); mTarget.removeOnDeviceProfileChangeListener(this); if (dp.isMultiWindowMode) { taskView.getRootView().addOnLayoutChangeListener( mTaskView.getRootView().addOnLayoutChangeListener( onLayoutChangeListener); } } }; dismissTaskMenuView(activity); dismissTaskMenuView(mTarget); ActivityOptions options = makeLaunchOptions(activity); ActivityOptions options = mFactory.makeLaunchOptions(mTarget); if (options != null && ActivityManagerWrapper.getInstance().startActivityFromRecents(taskId, options)) { if (!onActivityStarted(activity)) { 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 activity.addOnDeviceProfileChangeListener(onDeviceProfileChangeListener); 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 recentsView.setIgnoreResetTask(taskId); taskView.setAlpha(0f); mRecentsView.setIgnoreResetTask(taskId); mTaskView.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()); 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 = thumbnailView.getDimAlpha(); thumbnailView.setDimAlpha(0); float alpha = mThumbnailView.getDimAlpha(); mThumbnailView.setDimAlpha(0); Bitmap thumbnail = RecentsTransition.drawViewIntoHardwareBitmap( taskBounds.width(), taskBounds.height(), thumbnailView, 1f, taskBounds.width(), taskBounds.height(), mThumbnailView, 1f, Color.BLACK); thumbnailView.setDimAlpha(alpha); mThumbnailView.setDimAlpha(alpha); AppTransitionAnimationSpecsFuture future = new AppTransitionAnimationSpecsFuture(mHandler) { Loading @@ -202,16 +200,14 @@ public class TaskSystemShortcut<T extends SystemShortcut> extends SystemShortcut } }; WindowManagerWrapper.getInstance().overridePendingAppTransitionMultiThumbFuture( future, animStartedListener, mHandler, true /* scaleUp */, displayId); future, animStartedListener, mHandler, true /* scaleUp */, taskKey.displayId); } }); } } public static class SplitScreen extends MultiWindow { public SplitScreen() { super(R.drawable.ic_split_screen, R.string.recent_task_option_split_screen); } 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) { Loading Loading @@ -242,12 +238,10 @@ public class TaskSystemShortcut<T extends SystemShortcut> extends SystemShortcut 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); } TaskShortcutFactory FREE_FORM = new MultiWindowFactory( R.drawable.ic_split_screen, R.string.recent_task_option_freeform) { @Override protected boolean isAvailable(BaseDraggingActivity activity, int displayId) { Loading @@ -268,22 +262,9 @@ public class TaskSystemShortcut<T extends SystemShortcut> extends SystemShortcut 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) { TaskShortcutFactory PIN = (activity, tv) -> { if (!SystemUiProxy.INSTANCE.get(activity).isActive()) { return null; } Loading @@ -294,34 +275,38 @@ public class TaskSystemShortcut<T extends SystemShortcut> extends SystemShortcut // We shouldn't be able to pin while an app is locked. return null; } return view -> { 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(activity).startScreenPinning( taskView.getTask().key.id); SystemUiProxy.INSTANCE.get(mTarget).startScreenPinning( mTaskView.getTask().key.id); } else { taskView.notifyTaskLaunchFailed(TAG); mTaskView.notifyTaskLaunchFailed(TAG); } }; taskView.launchTask(true, resultCallback, mHandler); dismissTaskMenuView(activity); }; mTaskView.launchTask(true, resultCallback, Executors.MAIN_EXECUTOR.getHandler()); dismissTaskMenuView(mTarget); } } public static class Install extends TaskSystemShortcut<SystemShortcut.Install> { public Install() { super(new SystemShortcut.Install()); } TaskShortcutFactory INSTALL = (activity, view) -> InstantAppResolver.newInstance(activity).isInstantApp(activity, view.getTask().getTopComponent().getPackageName()) ? new SystemShortcut.Install(activity, dummyInfo(view)) : null; @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; } } }
quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskMenuView.java +5 −16 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -26,7 +25,6 @@ import android.content.Context; 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; Loading @@ -41,16 +39,13 @@ import com.android.launcher3.R; 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. */ Loading Loading @@ -197,22 +192,16 @@ public class TaskMenuView extends AbstractFloatingView { 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); } Loading
quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java +8 −20 Original line number Diff line number Diff line Loading @@ -53,6 +53,7 @@ import com.android.launcher3.Utilities; 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; Loading @@ -61,7 +62,6 @@ import com.android.launcher3.util.ViewPool.Reusable; 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; Loading Loading @@ -713,15 +713,9 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable { 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()) { Loading Loading @@ -752,16 +746,10 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable { 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; } } Loading
src/com/android/launcher3/popup/PopupContainerWithArrow.java +4 −6 Original line number Diff line number Diff line Loading @@ -382,8 +382,7 @@ public class PopupContainerWithArrow extends ArrowPopup implements DragSource, @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++) { Loading @@ -394,7 +393,7 @@ public class PopupContainerWithArrow extends ArrowPopup implements DragSource, } } 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( Loading @@ -407,7 +406,7 @@ public class PopupContainerWithArrow extends ArrowPopup implements DragSource, 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); Loading @@ -430,8 +429,7 @@ public class PopupContainerWithArrow extends ArrowPopup implements DragSource, info.setIconAndContentDescriptionFor((ImageView) view); } view.setTag(info); view.setOnClickListener(info.getOnClickListener(mLauncher, (ItemInfo) mOriginalIcon.getTag())); view.setOnClickListener(info); } /** Loading