diff --git a/quickstep/src/com/android/launcher3/popup/QuickstepSystemShortcut.java b/quickstep/src/com/android/launcher3/popup/QuickstepSystemShortcut.java index 3bc6576239..cc0072ebce 100644 --- a/quickstep/src/com/android/launcher3/popup/QuickstepSystemShortcut.java +++ b/quickstep/src/com/android/launcher3/popup/QuickstepSystemShortcut.java @@ -40,16 +40,12 @@ public interface QuickstepSystemShortcut { class SplitSelectSystemShortcut extends SystemShortcut { - private final BaseQuickstepLauncher mLauncher; - private final ItemInfo mItemInfo; private final SplitPositionOption mPosition; public SplitSelectSystemShortcut(BaseQuickstepLauncher launcher, ItemInfo itemInfo, SplitPositionOption position) { super(position.iconResId, position.textResId, launcher, itemInfo); - mLauncher = launcher; - mItemInfo = itemInfo; mPosition = position; } @@ -71,7 +67,7 @@ public interface QuickstepSystemShortcut { return; } - RecentsView recentsView = mLauncher.getOverviewPanel(); + RecentsView recentsView = mTarget.getOverviewPanel(); recentsView.initiateSplitSelect( new SplitSelectSource(view, new BitmapDrawable(bitmap), intent, mPosition)); } diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarPopupController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarPopupController.java index f9c806262a..1ccad78411 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarPopupController.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarPopupController.java @@ -15,14 +15,19 @@ */ package com.android.launcher3.taskbar; +import android.content.Intent; +import android.content.pm.LauncherApps; import android.graphics.Point; import android.view.MotionEvent; import android.view.View; import androidx.annotation.NonNull; +import com.android.launcher3.AbstractFloatingView; import com.android.launcher3.BubbleTextView; +import com.android.launcher3.LauncherSettings; import com.android.launcher3.R; +import com.android.launcher3.Utilities; import com.android.launcher3.dot.FolderDotInfo; import com.android.launcher3.folder.Folder; import com.android.launcher3.folder.FolderIcon; @@ -38,7 +43,9 @@ import com.android.launcher3.shortcuts.DeepShortcutView; import com.android.launcher3.util.ComponentKey; import com.android.launcher3.util.LauncherBindableItemsContainer; import com.android.launcher3.util.PackageUserKey; +import com.android.launcher3.util.SplitConfigurationOptions.SplitPositionOption; import com.android.launcher3.views.ActivityContext; +import com.android.quickstep.SystemUiProxy; import java.io.PrintWriter; import java.util.HashMap; @@ -151,7 +158,7 @@ public class TaskbarPopupController implements TaskbarControllers.LoggableTaskba mPopupDataProvider.getShortcutCountForItem(item), mPopupDataProvider.getNotificationKeysForItem(item), // TODO (b/198438631): add support for INSTALL shortcut factory - Stream.of(APP_INFO) + getSystemShortcuts() .map(s -> s.getShortcut(context, item)) .filter(Objects::nonNull) .collect(Collectors.toList())); @@ -167,6 +174,18 @@ public class TaskbarPopupController implements TaskbarControllers.LoggableTaskba return container; } + // Create a Stream of all applicable system shortcuts + // TODO(b/227800345): Add "Split bottom" option when tablet is in portrait mode. + private Stream getSystemShortcuts() { + // concat a Stream of split options with a Stream of APP_INFO + return Stream.concat( + Utilities.getSplitPositionOptions(mContext.getDeviceProfile()) + .stream() + .map(this::createSplitShortcutFactory), + Stream.of(APP_INFO) + ); + } + @Override public void dumpLogs(String prefix, PrintWriter pw) { pw.println(prefix + "TaskbarPopupController:"); @@ -213,4 +232,56 @@ public class TaskbarPopupController implements TaskbarControllers.LoggableTaskba return false; } } + + /** + * Creates a factory function representing a single "split position" menu item ("Split left," + * "Split right," or "Split top"). + * @param position A SplitPositionOption representing whether we are splitting top, left, or + * right. + * @return A factory function to be used in populating the long-press menu. + */ + private SystemShortcut.Factory createSplitShortcutFactory( + SplitPositionOption position) { + return (context, itemInfo) -> new TaskbarSplitShortcut(context, itemInfo, position); + } + + /** + * A single menu item ("Split left," "Split right," or "Split top") that executes a split + * from the taskbar, as if the user performed a drag and drop split. + * Includes an onClick method that initiates the actual split. + */ + private static class TaskbarSplitShortcut extends SystemShortcut { + private final SplitPositionOption mPosition; + + TaskbarSplitShortcut(BaseTaskbarContext context, ItemInfo itemInfo, + SplitPositionOption position) { + super(position.iconResId, position.textResId, context, itemInfo); + mPosition = position; + } + + @Override + public void onClick(View view) { + AbstractFloatingView.closeAllOpenViews(mTarget); + + if (mItemInfo.itemType == LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT) { + WorkspaceItemInfo workspaceItemInfo = (WorkspaceItemInfo) mItemInfo; + SystemUiProxy.INSTANCE.get(mTarget).startShortcut( + workspaceItemInfo.getIntent().getPackage(), + workspaceItemInfo.getDeepShortcutId(), + mPosition.stagePosition, + null, + workspaceItemInfo.user); + } else { + SystemUiProxy.INSTANCE.get(mTarget).startIntent( + mTarget.getSystemService(LauncherApps.class).getMainActivityLaunchIntent( + mItemInfo.getIntent().getComponent(), + null, + mItemInfo.user), + new Intent(), + mPosition.stagePosition, + null); + } + } + } } + diff --git a/src/com/android/launcher3/Utilities.java b/src/com/android/launcher3/Utilities.java index 9bc3d15da2..655ab5a90d 100644 --- a/src/com/android/launcher3/Utilities.java +++ b/src/com/android/launcher3/Utilities.java @@ -18,6 +18,9 @@ package com.android.launcher3; import static com.android.launcher3.icons.BitmapInfo.FLAG_THEMED; import static com.android.launcher3.model.data.ItemInfoWithIcon.FLAG_ICON_BADGED; +import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_BOTTOM_OR_RIGHT; +import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_TOP_OR_LEFT; +import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_TYPE_MAIN; import android.annotation.TargetApi; import android.app.ActivityManager; @@ -86,12 +89,14 @@ import com.android.launcher3.shortcuts.ShortcutKey; import com.android.launcher3.shortcuts.ShortcutRequest; import com.android.launcher3.util.IntArray; import com.android.launcher3.util.PackageManagerHelper; +import com.android.launcher3.util.SplitConfigurationOptions.SplitPositionOption; import com.android.launcher3.util.Themes; import com.android.launcher3.views.ActivityContext; import com.android.launcher3.views.BaseDragLayer; import com.android.launcher3.widget.PendingAddShortcutInfo; import java.lang.reflect.Method; +import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Locale; @@ -867,4 +872,39 @@ public final class Utilities { v.getLocationOnScreen(pos); return new Rect(pos[0], pos[1], pos[0] + v.getWidth(), pos[1] + v.getHeight()); } + + /** + * Returns a list of screen-splitting options depending on the device orientation (split top for + * portrait, split left for landscape, split left and right for landscape tablets, etc.) + */ + public static List getSplitPositionOptions( + DeviceProfile dp) { + List options = new ArrayList<>(); + // Add both left and right options if we're in tablet mode + if (dp.isTablet && dp.isLandscape) { + options.add(new SplitPositionOption( + R.drawable.ic_split_left, R.string.split_screen_position_left, + STAGE_POSITION_TOP_OR_LEFT, STAGE_TYPE_MAIN)); + options.add(new SplitPositionOption( + R.drawable.ic_split_right, R.string.split_screen_position_right, + STAGE_POSITION_BOTTOM_OR_RIGHT, STAGE_TYPE_MAIN)); + } else { + if (dp.isSeascape()) { + // Add left/right options + options.add(new SplitPositionOption( + R.drawable.ic_split_right, R.string.split_screen_position_right, + STAGE_POSITION_BOTTOM_OR_RIGHT, STAGE_TYPE_MAIN)); + } else if (dp.isLandscape) { + options.add(new SplitPositionOption( + R.drawable.ic_split_left, R.string.split_screen_position_left, + STAGE_POSITION_TOP_OR_LEFT, STAGE_TYPE_MAIN)); + } else { + // Only add top option + options.add(new SplitPositionOption( + R.drawable.ic_split_top, R.string.split_screen_position_top, + STAGE_POSITION_TOP_OR_LEFT, STAGE_TYPE_MAIN)); + } + } + return options; + } } diff --git a/src/com/android/launcher3/touch/PortraitPagedViewHandler.java b/src/com/android/launcher3/touch/PortraitPagedViewHandler.java index d88656c9f0..73c611583d 100644 --- a/src/com/android/launcher3/touch/PortraitPagedViewHandler.java +++ b/src/com/android/launcher3/touch/PortraitPagedViewHandler.java @@ -29,7 +29,6 @@ import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_Y; import static com.android.launcher3.touch.SingleAxisSwipeDetector.VERTICAL; import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_BOTTOM_OR_RIGHT; import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_TOP_OR_LEFT; -import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_TYPE_MAIN; import android.content.res.Resources; import android.graphics.Matrix; @@ -48,7 +47,6 @@ import android.widget.FrameLayout; import android.widget.LinearLayout; import com.android.launcher3.DeviceProfile; -import com.android.launcher3.R; import com.android.launcher3.Utilities; import com.android.launcher3.util.SplitConfigurationOptions; import com.android.launcher3.util.SplitConfigurationOptions.SplitPositionOption; @@ -56,7 +54,6 @@ import com.android.launcher3.util.SplitConfigurationOptions.StagePosition; import com.android.launcher3.util.SplitConfigurationOptions.StagedSplitBounds; import com.android.launcher3.views.BaseDragLayer; -import java.util.ArrayList; import java.util.List; public class PortraitPagedViewHandler implements PagedOrientationHandler { @@ -406,33 +403,7 @@ public class PortraitPagedViewHandler implements PagedOrientationHandler { @Override public List getSplitPositionOptions(DeviceProfile dp) { - List options = new ArrayList<>(1); - // Add both left and right options if we're in tablet mode - if (dp.isTablet && dp.isLandscape) { - options.add(new SplitPositionOption( - R.drawable.ic_split_left, R.string.split_screen_position_left, - STAGE_POSITION_TOP_OR_LEFT, STAGE_TYPE_MAIN)); - options.add(new SplitPositionOption( - R.drawable.ic_split_right, R.string.split_screen_position_right, - STAGE_POSITION_BOTTOM_OR_RIGHT, STAGE_TYPE_MAIN)); - } else { - if (dp.isSeascape()) { - // Add left/right options - options.add(new SplitPositionOption( - R.drawable.ic_split_right, R.string.split_screen_position_right, - STAGE_POSITION_BOTTOM_OR_RIGHT, STAGE_TYPE_MAIN)); - } else if (dp.isLandscape) { - options.add(new SplitPositionOption( - R.drawable.ic_split_left, R.string.split_screen_position_left, - STAGE_POSITION_TOP_OR_LEFT, STAGE_TYPE_MAIN)); - } else { - // Only add top option - options.add(new SplitPositionOption( - R.drawable.ic_split_top, R.string.split_screen_position_top, - STAGE_POSITION_TOP_OR_LEFT, STAGE_TYPE_MAIN)); - } - } - return options; + return Utilities.getSplitPositionOptions(dp); } @Override