mirror of
https://github.com/LawnchairLauncher/lawnchair.git
synced 2026-02-20 03:08:19 +00:00
Merge "Implement split from workspace to workspace" into tm-qpr-dev
This commit is contained in:
@@ -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 @@ public interface QuickstepSystemShortcut {
|
||||
|
||||
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 @@ public interface QuickstepSystemShortcut {
|
||||
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 @@ public interface QuickstepSystemShortcut {
|
||||
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 interface QuickstepSystemShortcut {
|
||||
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 @@ public interface QuickstepSystemShortcut {
|
||||
this.drawable = drawable;
|
||||
this.intent = intent;
|
||||
this.position = position;
|
||||
this.mItemInfo = itemInfo;
|
||||
this.itemInfo = itemInfo;
|
||||
this.splitEvent = splitEvent;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,6 +95,7 @@ import com.android.launcher3.logging.StatsLogManager.StatsLogger;
|
||||
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.QuickstepOnboardingPrefs;
|
||||
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 @@ public class QuickstepLauncher extends Launcher {
|
||||
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 @@ public class QuickstepLauncher extends Launcher {
|
||||
|
||||
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 @@ public class QuickstepLauncher extends Launcher {
|
||||
}
|
||||
|
||||
protected void onItemClicked(View view) {
|
||||
if (!mSplitWithKeyboardShortcutController.handleSecondAppSelectionForSplit(view)) {
|
||||
if (!mSplitToWorkspaceController.handleSecondAppSelectionForSplit(view)) {
|
||||
QuickstepLauncher.super.getItemOnClickListener().onClick(view);
|
||||
}
|
||||
}
|
||||
@@ -724,6 +731,10 @@ public class QuickstepLauncher extends Launcher {
|
||||
return mTaskbarUIController;
|
||||
}
|
||||
|
||||
public SplitSelectStateController getSplitSelectStateController() {
|
||||
return mSplitSelectStateController;
|
||||
}
|
||||
|
||||
public <T extends OverviewActionsView> T getActionsView() {
|
||||
return (T) mActionsView;
|
||||
}
|
||||
|
||||
@@ -561,6 +561,20 @@ public class SystemUiProxy implements ISystemUiProxy {
|
||||
}
|
||||
}
|
||||
|
||||
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 class SystemUiProxy implements ISystemUiProxy {
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
|
||||
@@ -37,6 +37,7 @@ import android.os.Handler;
|
||||
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 @@ public class SplitSelectStateController {
|
||||
* 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 @@ public class SplitSelectStateController {
|
||||
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 @@ public class SplitSelectStateController {
|
||||
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 @@ public class SplitSelectStateController {
|
||||
: PendingIntent.getActivity(mContext, 0, intent, FLAG_MUTABLE));
|
||||
}
|
||||
|
||||
|
||||
public @StagePosition int getActiveSplitStagePosition() {
|
||||
return mStagePosition;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -101,33 +101,6 @@ public class SplitWithKeyboardShortcutController {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 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();
|
||||
}
|
||||
|
||||
@@ -4265,7 +4265,7 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
|
||||
public void initiateSplitSelect(QuickstepSystemShortcut.SplitSelectSource splitSelectSource) {
|
||||
mSplitSelectSource = splitSelectSource;
|
||||
mSplitSelectStateController.setInitialTaskSelect(splitSelectSource.intent,
|
||||
splitSelectSource.position.stagePosition, splitSelectSource.mItemInfo,
|
||||
splitSelectSource.position.stagePosition, splitSelectSource.itemInfo,
|
||||
splitSelectSource.splitEvent);
|
||||
}
|
||||
|
||||
|
||||
@@ -258,6 +258,10 @@ public final class FeatureFlags {
|
||||
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");
|
||||
|
||||
Reference in New Issue
Block a user