Merge "Implement split from workspace to workspace" into tm-qpr-dev
diff --git a/quickstep/src/com/android/launcher3/popup/QuickstepSystemShortcut.java b/quickstep/src/com/android/launcher3/popup/QuickstepSystemShortcut.java
index 7c3281a..7cf8201 100644
--- a/quickstep/src/com/android/launcher3/popup/QuickstepSystemShortcut.java
+++ b/quickstep/src/com/android/launcher3/popup/QuickstepSystemShortcut.java
@@ -15,20 +15,29 @@
*/
package com.android.launcher3.popup;
+import static com.android.launcher3.config.FeatureFlags.ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE;
import static com.android.launcher3.util.SplitConfigurationOptions.getLogEventForPosition;
+import static com.android.quickstep.util.SplitAnimationTimings.TABLET_HOME_TO_SPLIT;
import android.content.Intent;
import android.graphics.Bitmap;
+import android.graphics.Rect;
+import android.graphics.RectF;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.util.Log;
import android.view.View;
+import com.android.launcher3.AbstractFloatingView;
+import com.android.launcher3.R;
+import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.logging.StatsLogManager;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.model.data.WorkspaceItemInfo;
import com.android.launcher3.uioverrides.QuickstepLauncher;
import com.android.launcher3.util.SplitConfigurationOptions.SplitPositionOption;
+import com.android.quickstep.util.SplitSelectStateController;
+import com.android.quickstep.views.FloatingTaskView;
import com.android.quickstep.views.RecentsView;
public interface QuickstepSystemShortcut {
@@ -44,6 +53,10 @@
class SplitSelectSystemShortcut extends SystemShortcut<QuickstepLauncher> {
+ private final int mSplitPlaceholderSize;
+ private final int mSplitPlaceholderInset;
+
+ private final Rect mTempRect = new Rect();
private final SplitPositionOption mPosition;
public SplitSelectSystemShortcut(QuickstepLauncher launcher, ItemInfo itemInfo,
@@ -51,6 +64,11 @@
super(position.iconResId, position.textResId, launcher, itemInfo, originalView);
mPosition = position;
+
+ mSplitPlaceholderSize = launcher.getResources().getDimensionPixelSize(
+ R.dimen.split_placeholder_size);
+ mSplitPlaceholderInset = launcher.getResources().getDimensionPixelSize(
+ R.dimen.split_placeholder_inset);
}
@Override
@@ -72,11 +90,39 @@
return;
}
- RecentsView recentsView = mTarget.getOverviewPanel();
StatsLogManager.EventEnum splitEvent = getLogEventForPosition(mPosition.stagePosition);
- recentsView.initiateSplitSelect(
- new SplitSelectSource(mOriginalView, new BitmapDrawable(bitmap), intent,
- mPosition, mItemInfo, splitEvent));
+ SplitSelectSource source = new SplitSelectSource(mOriginalView,
+ new BitmapDrawable(bitmap), intent, mPosition, mItemInfo, splitEvent);
+ if (ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE.get()) {
+ startSplitToHome(source);
+ } else {
+ RecentsView recentsView = mTarget.getOverviewPanel();
+ recentsView.initiateSplitSelect(source);
+ }
+ }
+
+ private void startSplitToHome(SplitSelectSource source) {
+ AbstractFloatingView.closeAllOpenViews(mTarget);
+
+ SplitSelectStateController controller = mTarget.getSplitSelectStateController();
+ controller.setInitialTaskSelect(source.intent, source.position.stagePosition,
+ source.itemInfo, source.splitEvent);
+
+ RecentsView recentsView = mTarget.getOverviewPanel();
+ recentsView.getPagedOrientationHandler().getInitialSplitPlaceholderBounds(
+ mSplitPlaceholderSize, mSplitPlaceholderInset, mTarget.getDeviceProfile(),
+ controller.getActiveSplitStagePosition(), mTempRect);
+
+ PendingAnimation anim = new PendingAnimation(TABLET_HOME_TO_SPLIT.getDuration());
+ RectF startingTaskRect = new RectF();
+ FloatingTaskView floatingTaskView = FloatingTaskView.getFloatingTaskView(mTarget,
+ source.view, null /* thumbnail */,
+ source.drawable, startingTaskRect);
+ floatingTaskView.setAlpha(1);
+ floatingTaskView.addStagingAnimation(anim, startingTaskRect, mTempRect,
+ false /* fadeWithThumbnail */, true /* isStagedTask */);
+ controller.setFirstFloatingTaskView(floatingTaskView);
+ anim.buildAnim().start();
}
}
@@ -86,7 +132,7 @@
public final Drawable drawable;
public final Intent intent;
public final SplitPositionOption position;
- public final ItemInfo mItemInfo;
+ public final ItemInfo itemInfo;
public final StatsLogManager.EventEnum splitEvent;
public SplitSelectSource(View view, Drawable drawable, Intent intent,
@@ -96,7 +142,7 @@
this.drawable = drawable;
this.intent = intent;
this.position = position;
- this.mItemInfo = itemInfo;
+ this.itemInfo = itemInfo;
this.splitEvent = splitEvent;
}
}
diff --git a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
index f90feb8..36d9686 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
@@ -95,6 +95,7 @@
import com.android.launcher3.model.BgDataModel.FixedContainerItems;
import com.android.launcher3.model.WellbeingModel;
import com.android.launcher3.model.data.ItemInfo;
+import com.android.launcher3.model.data.WorkspaceItemInfo;
import com.android.launcher3.popup.SystemShortcut;
import com.android.launcher3.proxy.ProxyActivityStarter;
import com.android.launcher3.proxy.StartActivityParams;
@@ -136,6 +137,7 @@
import com.android.quickstep.util.RemoteAnimationProvider;
import com.android.quickstep.util.RemoteFadeOutAnimationListener;
import com.android.quickstep.util.SplitSelectStateController;
+import com.android.quickstep.util.SplitToWorkspaceController;
import com.android.quickstep.util.SplitWithKeyboardShortcutController;
import com.android.quickstep.util.TISBindHelper;
import com.android.quickstep.views.OverviewActionsView;
@@ -182,7 +184,10 @@
private @Nullable RotationChangeProvider mRotationChangeProvider;
private @Nullable LauncherUnfoldAnimationController mLauncherUnfoldAnimationController;
+ private SplitSelectStateController mSplitSelectStateController;
private SplitWithKeyboardShortcutController mSplitWithKeyboardShortcutController;
+ private SplitToWorkspaceController mSplitToWorkspaceController;
+
/**
* If Launcher restarted while in the middle of an Overview split select, it needs this data to
* recover. In all other cases this will remain null.
@@ -199,12 +204,14 @@
mActionsView = findViewById(R.id.overview_actions_view);
RecentsView overviewPanel = getOverviewPanel();
- SplitSelectStateController controller =
+ mSplitSelectStateController =
new SplitSelectStateController(this, mHandler, getStateManager(),
getDepthController(), getStatsLogManager());
- overviewPanel.init(mActionsView, controller);
+ overviewPanel.init(mActionsView, mSplitSelectStateController);
mSplitWithKeyboardShortcutController = new SplitWithKeyboardShortcutController(this,
- controller);
+ mSplitSelectStateController);
+ mSplitToWorkspaceController = new SplitToWorkspaceController(this,
+ mSplitSelectStateController);
mActionsView.updateDimension(getDeviceProfile(), overviewPanel.getLastComputedTaskSize());
mActionsView.updateVerticalMargin(DisplayController.getNavigationMode(this));
@@ -330,7 +337,7 @@
}
protected void onItemClicked(View view) {
- if (!mSplitWithKeyboardShortcutController.handleSecondAppSelectionForSplit(view)) {
+ if (!mSplitToWorkspaceController.handleSecondAppSelectionForSplit(view)) {
QuickstepLauncher.super.getItemOnClickListener().onClick(view);
}
}
@@ -724,6 +731,10 @@
return mTaskbarUIController;
}
+ public SplitSelectStateController getSplitSelectStateController() {
+ return mSplitSelectStateController;
+ }
+
public <T extends OverviewActionsView> T getActionsView() {
return (T) mActionsView;
}
diff --git a/quickstep/src/com/android/quickstep/SystemUiProxy.java b/quickstep/src/com/android/quickstep/SystemUiProxy.java
index ef7c6dc..bb97334 100644
--- a/quickstep/src/com/android/quickstep/SystemUiProxy.java
+++ b/quickstep/src/com/android/quickstep/SystemUiProxy.java
@@ -561,6 +561,20 @@
}
}
+ public void startIntents(PendingIntent pendingIntent1, Bundle options1,
+ PendingIntent pendingIntent2, Bundle options2,
+ @SplitConfigurationOptions.StagePosition int splitPosition,
+ float splitRatio, RemoteTransition remoteTransition, InstanceId instanceId) {
+ if (mSystemUiProxy != null) {
+ try {
+ mSplitScreen.startIntents(pendingIntent1, options1, pendingIntent2, options2,
+ splitPosition, splitRatio, remoteTransition, instanceId);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed call startIntents");
+ }
+ }
+ }
+
public void startShortcutAndTask(ShortcutInfo shortcutInfo, Bundle options1, int taskId,
Bundle options2, @SplitConfigurationOptions.StagePosition int splitPosition,
float splitRatio, RemoteTransition remoteTransition, InstanceId instanceId) {
@@ -617,6 +631,20 @@
}
}
+ public void startIntentsWithLegacyTransition(PendingIntent pendingIntent1, Bundle options1,
+ PendingIntent pendingIntent2, Bundle options2,
+ @SplitConfigurationOptions.StagePosition int sidePosition, float splitRatio,
+ RemoteAnimationAdapter adapter, InstanceId instanceId) {
+ if (mSystemUiProxy != null) {
+ try {
+ mSplitScreen.startIntentsWithLegacyTransition(pendingIntent1, options1,
+ pendingIntent2, options2, sidePosition, splitRatio, adapter, instanceId);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed call startIntentsWithLegacyTransition");
+ }
+ }
+ }
+
public void startShortcut(String packageName, String shortcutId, int position,
Bundle options, UserHandle user, InstanceId instanceId) {
if (mSplitScreen != null) {
diff --git a/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java b/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java
index 4a74ac6..c263fe8 100644
--- a/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java
+++ b/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java
@@ -37,6 +37,7 @@
import android.os.IBinder;
import android.os.RemoteException;
import android.os.UserHandle;
+import android.text.TextUtils;
import android.util.Log;
import android.util.Pair;
import android.view.RemoteAnimationAdapter;
@@ -207,8 +208,8 @@
* fill in intent with a taskId2 are set.
* @param intent1 is null when split is initiated from Overview
* @param stagePosition representing location of task1
- * @param shellInstanceId loggingId to be used by shell, will be non-null for actions that create
- * a split instance, null for cases that bring existing instaces to the
+ * @param shellInstanceId loggingId to be used by shell, will be non-null for actions that
+ * create a split instance, null for cases that bring existing instaces to the
* foreground (quickswitch, launching previous pairs from overview)
*/
public void launchTasks(int taskId1, @Nullable Intent intent1, int taskId2,
@@ -238,7 +239,9 @@
getOppositeStagePosition(stagePosition), splitRatio, remoteTransition,
shellInstanceId);
} else {
- // TODO: the case when both split apps are started from an intent.
+ mSystemUiProxy.startIntents(getPendingIntent(intent1), options1.toBundle(),
+ getPendingIntent(intent2), null /* options2 */, stagePosition,
+ splitRatio, remoteTransition, shellInstanceId);
}
} else {
final RemoteSplitLaunchAnimationRunner animationRunner =
@@ -259,7 +262,9 @@
getOppositeStagePosition(stagePosition), splitRatio, adapter,
shellInstanceId);
} else {
- // TODO: the case when both split apps are started from an intent.
+ mSystemUiProxy.startIntentsWithLegacyTransition(getPendingIntent(intent1),
+ options1.toBundle(), getPendingIntent(intent2), null /* options2 */,
+ stagePosition, splitRatio, adapter, shellInstanceId);
}
}
}
@@ -305,7 +310,6 @@
: PendingIntent.getActivity(mContext, 0, intent, FLAG_MUTABLE));
}
-
public @StagePosition int getActiveSplitStagePosition() {
return mStagePosition;
}
diff --git a/quickstep/src/com/android/quickstep/util/SplitToWorkspaceController.java b/quickstep/src/com/android/quickstep/util/SplitToWorkspaceController.java
new file mode 100644
index 0000000..e8a4b0a
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/util/SplitToWorkspaceController.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2022 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.util;
+
+import static com.android.launcher3.config.FeatureFlags.ENABLE_SPLIT_FROM_FULLSCREEN_WITH_KEYBOARD_SHORTCUTS;
+import static com.android.launcher3.config.FeatureFlags.ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE;
+
+import android.content.Intent;
+import android.view.View;
+
+import com.android.launcher3.Launcher;
+import com.android.launcher3.model.data.WorkspaceItemInfo;
+
+/** Handles when the stage split lands on the home screen. */
+public class SplitToWorkspaceController {
+
+ private final Launcher mLauncher;
+ private final SplitSelectStateController mController;
+
+ public SplitToWorkspaceController(Launcher launcher, SplitSelectStateController controller) {
+ mLauncher = launcher;
+ mController = controller;
+ }
+
+ /**
+ * Handles second app selection from stage split. If the item can't be opened in split or
+ * it's not in stage split state, we pass it onto Launcher's default item click handler.
+ */
+ public boolean handleSecondAppSelectionForSplit(View view) {
+ if ((!ENABLE_SPLIT_FROM_FULLSCREEN_WITH_KEYBOARD_SHORTCUTS.get()
+ && !ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE.get())
+ || !mController.isSplitSelectActive()) {
+ return false;
+ }
+ Object tag = view.getTag();
+ Intent intent;
+ if (tag instanceof WorkspaceItemInfo) {
+ final WorkspaceItemInfo workspaceItemInfo = (WorkspaceItemInfo) tag;
+ intent = workspaceItemInfo.intent;
+ } else if (tag instanceof com.android.launcher3.model.data.AppInfo) {
+ final com.android.launcher3.model.data.AppInfo appInfo =
+ (com.android.launcher3.model.data.AppInfo) tag;
+ intent = appInfo.intent;
+ } else {
+ return false;
+ }
+ mController.setSecondTask(intent);
+ mController.launchSplitTasks(aBoolean -> mLauncher.getDragLayer().removeView(
+ mController.getFirstFloatingTaskView()));
+ return true;
+ }
+}
diff --git a/quickstep/src/com/android/quickstep/util/SplitWithKeyboardShortcutController.java b/quickstep/src/com/android/quickstep/util/SplitWithKeyboardShortcutController.java
index 3587bd1..24d8326 100644
--- a/quickstep/src/com/android/quickstep/util/SplitWithKeyboardShortcutController.java
+++ b/quickstep/src/com/android/quickstep/util/SplitWithKeyboardShortcutController.java
@@ -101,33 +101,6 @@
});
}
- /**
- * Handles second app selection from stage split. If the item can't be opened in split or
- * it's not in stage split state, we pass it onto Launcher's default item click handler.
- */
- public boolean handleSecondAppSelectionForSplit(View view) {
- if (!ENABLE_SPLIT_FROM_FULLSCREEN_WITH_KEYBOARD_SHORTCUTS.get()
- || !mController.isSplitSelectActive()) {
- return false;
- }
- Object tag = view.getTag();
- Intent intent;
- if (tag instanceof WorkspaceItemInfo) {
- final WorkspaceItemInfo workspaceItemInfo = (WorkspaceItemInfo) tag;
- intent = workspaceItemInfo.intent;
- } else if (tag instanceof com.android.launcher3.model.data.AppInfo) {
- final com.android.launcher3.model.data.AppInfo appInfo =
- (com.android.launcher3.model.data.AppInfo) tag;
- intent = appInfo.intent;
- } else {
- return false;
- }
- mController.setSecondTask(intent);
- mController.launchSplitTasks(aBoolean -> mLauncher.getDragLayer().removeView(
- mController.getFirstFloatingTaskView()));
- return true;
- }
-
public void onDestroy() {
mOverviewComponentObserver.onDestroy();
}
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index 2474b69..80b41a7 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -4265,7 +4265,7 @@
public void initiateSplitSelect(QuickstepSystemShortcut.SplitSelectSource splitSelectSource) {
mSplitSelectSource = splitSelectSource;
mSplitSelectStateController.setInitialTaskSelect(splitSelectSource.intent,
- splitSelectSource.position.stagePosition, splitSelectSource.mItemInfo,
+ splitSelectSource.position.stagePosition, splitSelectSource.itemInfo,
splitSelectSource.splitEvent);
}
diff --git a/src/com/android/launcher3/config/FeatureFlags.java b/src/com/android/launcher3/config/FeatureFlags.java
index e20489c..9607da8 100644
--- a/src/com/android/launcher3/config/FeatureFlags.java
+++ b/src/com/android/launcher3/config/FeatureFlags.java
@@ -258,6 +258,10 @@
getDebugFlag("ENABLE_SPLIT_FROM_FULLSCREEN_SHORTCUT", false,
"Enable splitting from fullscreen app with keyboard shortcuts");
+ public static final BooleanFlag ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE = getDebugFlag(
+ "ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE", false,
+ "Enable initiating split screen from workspace to workspace.");
+
public static final BooleanFlag ENABLE_NEW_MIGRATION_LOGIC = getDebugFlag(
"ENABLE_NEW_MIGRATION_LOGIC", true,
"Enable the new grid migration logic, keeping pages when src < dest");