mirror of
https://github.com/LawnchairLauncher/lawnchair.git
synced 2026-02-19 10:48:19 +00:00
Merge "Allow starting split from home, selecting second app from overview" into udc-qpr-dev
This commit is contained in:
@@ -46,6 +46,7 @@ import androidx.annotation.NonNull;
|
||||
import com.android.launcher3.LauncherState;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.anim.PendingAnimation;
|
||||
import com.android.launcher3.config.FeatureFlags;
|
||||
import com.android.launcher3.dragndrop.DragLayer;
|
||||
import com.android.launcher3.statemanager.StateManager.StateHandler;
|
||||
import com.android.launcher3.states.StateAnimationConfig;
|
||||
@@ -113,7 +114,9 @@ public abstract class BaseRecentsViewStateController<T extends RecentsView>
|
||||
setter.setFloat(mRecentsView, TASK_SECONDARY_TRANSLATION, 0f,
|
||||
config.getInterpolator(ANIM_OVERVIEW_TRANSLATE_Y, LINEAR));
|
||||
|
||||
if (mRecentsView.isSplitSelectionActive()) {
|
||||
boolean exitingOverview = !FeatureFlags.ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE.get()
|
||||
|| !toState.overviewUi;
|
||||
if (mRecentsView.isSplitSelectionActive() && exitingOverview) {
|
||||
// TODO (b/238651489): Refactor state management to avoid need for double check
|
||||
FloatingTaskView floatingTask = mRecentsView.getFirstFloatingTaskView();
|
||||
if (floatingTask != null) {
|
||||
|
||||
@@ -615,9 +615,10 @@ public class QuickstepLauncher extends Launcher {
|
||||
mSplitSelectStateController.findLastActiveTaskAndRunCallback(
|
||||
splitSelectSource.itemInfo.getComponentKey(),
|
||||
foundTask -> {
|
||||
splitSelectSource.alreadyRunningTaskId = foundTask == null
|
||||
? INVALID_TASK_ID
|
||||
: foundTask.key.id;
|
||||
boolean taskWasFound = foundTask != null;
|
||||
splitSelectSource.alreadyRunningTaskId = taskWasFound
|
||||
? foundTask.key.id
|
||||
: INVALID_TASK_ID;
|
||||
if (ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE.get()) {
|
||||
startSplitToHome(splitSelectSource);
|
||||
} else {
|
||||
@@ -1295,7 +1296,7 @@ public class QuickstepLauncher extends Launcher {
|
||||
groupTask.task1.key.id,
|
||||
groupTask.task2.key.id,
|
||||
SplitConfigurationOptions.STAGE_POSITION_TOP_OR_LEFT,
|
||||
/* callback= */ success -> {},
|
||||
/* callback= */ success -> mSplitSelectStateController.resetState(),
|
||||
/* freezeTaskList= */ true,
|
||||
groupTask.mSplitBounds == null
|
||||
? DEFAULT_SPLIT_RATIO
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.android.quickstep
|
||||
|
||||
interface SplitSelectionListener {
|
||||
/** Called when the first app has been selected with the intention to launch split screen */
|
||||
fun onSplitSelectionActive()
|
||||
|
||||
/** Called when the second app has been selected with the intention to launch split screen */
|
||||
fun onSplitSelectionConfirmed()
|
||||
|
||||
/**
|
||||
* Called when the user no longer is in the process of selecting apps for split screen.
|
||||
* [launchedSplit] will be true if selected apps have launched successfully (either in
|
||||
* split screen or fullscreen), false if the user canceled/exited the selection process
|
||||
*/
|
||||
fun onSplitSelectionExit(launchedSplit: Boolean) {
|
||||
}
|
||||
}
|
||||
@@ -35,6 +35,7 @@ import androidx.annotation.Nullable;
|
||||
import com.android.launcher3.AbstractFloatingView;
|
||||
import com.android.launcher3.anim.AnimatorPlaybackController;
|
||||
import com.android.launcher3.anim.PendingAnimation;
|
||||
import com.android.launcher3.config.FeatureFlags;
|
||||
import com.android.launcher3.logging.StatsLogManager;
|
||||
import com.android.launcher3.statemanager.StateManager.StateListener;
|
||||
import com.android.launcher3.util.SplitConfigurationOptions;
|
||||
@@ -246,7 +247,11 @@ public class FallbackRecentsView extends RecentsView<RecentsActivity, RecentsSta
|
||||
setOverviewSelectEnabled(false);
|
||||
}
|
||||
if (finalState != OVERVIEW_SPLIT_SELECT) {
|
||||
resetFromSplitSelectionState();
|
||||
if (FeatureFlags.ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE.get()) {
|
||||
mSplitSelectStateController.resetState();
|
||||
} else {
|
||||
resetFromSplitSelectionState();
|
||||
}
|
||||
}
|
||||
|
||||
if (isOverlayEnabled) {
|
||||
|
||||
@@ -73,16 +73,18 @@ import com.android.launcher3.util.ComponentKey;
|
||||
import com.android.launcher3.util.SplitConfigurationOptions;
|
||||
import com.android.launcher3.util.SplitConfigurationOptions.StagePosition;
|
||||
import com.android.quickstep.RecentsModel;
|
||||
import com.android.quickstep.SplitSelectionListener;
|
||||
import com.android.quickstep.SystemUiProxy;
|
||||
import com.android.quickstep.TaskAnimationManager;
|
||||
import com.android.quickstep.TaskViewUtils;
|
||||
import com.android.quickstep.views.FloatingTaskView;
|
||||
import com.android.quickstep.views.GroupedTaskView;
|
||||
import com.android.quickstep.views.TaskView;
|
||||
import com.android.systemui.shared.recents.model.Task;
|
||||
import com.android.systemui.shared.system.RemoteAnimationRunnerCompat;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
@@ -138,6 +140,8 @@ public class SplitSelectStateController {
|
||||
|
||||
private FloatingTaskView mFirstFloatingTaskView;
|
||||
|
||||
private final List<SplitSelectionListener> mSplitSelectionListeners = new ArrayList<>();
|
||||
|
||||
public SplitSelectStateController(Context context, Handler handler, StateManager stateManager,
|
||||
DepthController depthController, StatsLogManager statsLogManager,
|
||||
SystemUiProxy systemUiProxy, RecentsModel recentsModel) {
|
||||
@@ -247,6 +251,27 @@ public class SplitSelectStateController {
|
||||
&& task.key.userId == componentKey.user.getIdentifier();
|
||||
}
|
||||
|
||||
/**
|
||||
* Listener will only get callbacks going forward from the point of registration. No
|
||||
* methods will be fired upon registering.
|
||||
*/
|
||||
public void registerSplitListener(@NonNull SplitSelectionListener listener) {
|
||||
if (mSplitSelectionListeners.contains(listener)) {
|
||||
return;
|
||||
}
|
||||
mSplitSelectionListeners.add(listener);
|
||||
}
|
||||
|
||||
public void unregisterSplitListener(@NonNull SplitSelectionListener listener) {
|
||||
mSplitSelectionListeners.remove(listener);
|
||||
}
|
||||
|
||||
private void dispatchOnSplitSelectionExit() {
|
||||
for (SplitSelectionListener listener : mSplitSelectionListeners) {
|
||||
listener.onSplitSelectionExit(false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* To be called when the actual tasks ({@link #mInitialTaskId}, {@link #mSecondTaskId}) are
|
||||
* to be launched. Call after launcher side animations are complete.
|
||||
@@ -790,12 +815,16 @@ public class SplitSelectStateController {
|
||||
}
|
||||
|
||||
/**
|
||||
* To be called if split select was cancelled
|
||||
* To be called whenever we exit split selection state. If
|
||||
* {@link FeatureFlags#ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE} is set, this should be the
|
||||
* central way split is getting reset, which should then go through the callbacks to reset
|
||||
* other state.
|
||||
*/
|
||||
public void resetState() {
|
||||
if (FeatureFlags.ENABLE_SPLIT_LAUNCH_DATA_REFACTOR.get()) {
|
||||
mSplitSelectDataHolder.resetState();
|
||||
}
|
||||
dispatchOnSplitSelectionExit();
|
||||
mInitialTaskId = INVALID_TASK_ID;
|
||||
mInitialTaskIntent = null;
|
||||
mSecondTaskId = INVALID_TASK_ID;
|
||||
|
||||
@@ -37,6 +37,7 @@ import androidx.annotation.Nullable;
|
||||
|
||||
import com.android.launcher3.AbstractFloatingView;
|
||||
import com.android.launcher3.LauncherState;
|
||||
import com.android.launcher3.config.FeatureFlags;
|
||||
import com.android.launcher3.logging.StatsLogManager;
|
||||
import com.android.launcher3.statehandlers.DepthController;
|
||||
import com.android.launcher3.statehandlers.DesktopVisibilityController;
|
||||
@@ -218,7 +219,11 @@ public class LauncherRecentsView extends RecentsView<QuickstepLauncher, Launcher
|
||||
|
||||
@Override
|
||||
protected boolean canLaunchFullscreenTask() {
|
||||
return !mActivity.isInState(OVERVIEW_SPLIT_SELECT);
|
||||
if (FeatureFlags.ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE.get()) {
|
||||
return !mSplitSelectStateController.isSplitSelectActive();
|
||||
} else {
|
||||
return !mActivity.isInState(OVERVIEW_SPLIT_SELECT);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -173,6 +173,7 @@ import com.android.quickstep.RemoteAnimationTargets;
|
||||
import com.android.quickstep.RemoteTargetGluer;
|
||||
import com.android.quickstep.RemoteTargetGluer.RemoteTargetHandle;
|
||||
import com.android.quickstep.RotationTouchHelper;
|
||||
import com.android.quickstep.SplitSelectionListener;
|
||||
import com.android.quickstep.SystemUiProxy;
|
||||
import com.android.quickstep.TaskOverlayFactory;
|
||||
import com.android.quickstep.TaskThumbnailCache;
|
||||
@@ -662,7 +663,8 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
|
||||
/**
|
||||
* Placeholder view indicating where the first split screen selected app will be placed
|
||||
*/
|
||||
private SplitSelectStateController mSplitSelectStateController;
|
||||
protected SplitSelectStateController mSplitSelectStateController;
|
||||
|
||||
/**
|
||||
* The first task that split screen selection was initiated with. When split select state is
|
||||
* initialized, we create a
|
||||
@@ -685,6 +687,19 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
|
||||
@Nullable
|
||||
private SplitSelectSource mSplitSelectSource;
|
||||
|
||||
private final SplitSelectionListener mSplitSelectionListener = new SplitSelectionListener() {
|
||||
@Override
|
||||
public void onSplitSelectionConfirmed() { }
|
||||
|
||||
@Override
|
||||
public void onSplitSelectionActive() { }
|
||||
|
||||
@Override
|
||||
public void onSplitSelectionExit(boolean launchedSplit) {
|
||||
resetFromSplitSelectionState();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Keeps track of the index of the TaskView that split screen was initialized with so we know
|
||||
* where to insert it back into list of taskViews in case user backs out of entering split
|
||||
@@ -1065,6 +1080,9 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
|
||||
mIPipAnimationListener);
|
||||
mOrientationState.initListeners();
|
||||
mTaskOverlayFactory.initListeners();
|
||||
if (FeatureFlags.ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE.get()) {
|
||||
mSplitSelectStateController.registerSplitListener(mSplitSelectionListener);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1083,6 +1101,9 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
|
||||
mIPipAnimationListener.setActivityAndRecentsView(null, null);
|
||||
mOrientationState.destroyListeners();
|
||||
mTaskOverlayFactory.removeListeners();
|
||||
if (FeatureFlags.ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE.get()) {
|
||||
mSplitSelectStateController.unregisterSplitListener(mSplitSelectionListener);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1660,8 +1681,8 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
|
||||
// If we are entering Overview as a result of initiating a split from somewhere else
|
||||
// (e.g. split from Home), we need to make sure the staged app is not drawn as a thumbnail.
|
||||
int stagedTaskIdToBeRemovedFromGrid;
|
||||
if (mSplitSelectSource != null) {
|
||||
stagedTaskIdToBeRemovedFromGrid = mSplitSelectSource.alreadyRunningTaskId;
|
||||
if (isSplitSelectionActive()) {
|
||||
stagedTaskIdToBeRemovedFromGrid = mSplitSelectStateController.getInitialTaskId();
|
||||
updateCurrentTaskActionsVisibility();
|
||||
} else {
|
||||
stagedTaskIdToBeRemovedFromGrid = INVALID_TASK_ID;
|
||||
@@ -2367,7 +2388,9 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
|
||||
remoteTargetHandle.getTransformParams().setTargetSet(null);
|
||||
remoteTargetHandle.getTaskViewSimulator().setDrawsBelowRecents(false);
|
||||
});
|
||||
resetFromSplitSelectionState();
|
||||
if (!FeatureFlags.ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE.get()) {
|
||||
resetFromSplitSelectionState();
|
||||
}
|
||||
|
||||
// These are relatively expensive and don't need to be done this frame (RecentsView isn't
|
||||
// visible anyway), so defer by a frame to get off the critical path, e.g. app to home.
|
||||
@@ -3251,7 +3274,11 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
|
||||
InteractionJankMonitorWrapper.CUJ_SPLIT_SCREEN_ENTER);
|
||||
} else {
|
||||
// If transition to split select was interrupted, clean up to prevent glitches
|
||||
resetFromSplitSelectionState();
|
||||
if (FeatureFlags.ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE.get()) {
|
||||
mSplitSelectStateController.resetState();
|
||||
} else {
|
||||
resetFromSplitSelectionState();
|
||||
}
|
||||
InteractionJankMonitorWrapper.cancel(
|
||||
InteractionJankMonitorWrapper.CUJ_SPLIT_SCREEN_ENTER);
|
||||
}
|
||||
@@ -3284,8 +3311,13 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
|
||||
true /* isStagedTask */);
|
||||
|
||||
pendingAnimation.addEndListener(animationSuccess ->
|
||||
mSplitSelectStateController.launchInitialAppFullscreen(launchSuccess ->
|
||||
resetFromSplitSelectionState()));
|
||||
mSplitSelectStateController.launchInitialAppFullscreen(launchSuccess -> {
|
||||
if (FeatureFlags.ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE.get()) {
|
||||
mSplitSelectStateController.resetState();
|
||||
} else {
|
||||
resetFromSplitSelectionState();
|
||||
}
|
||||
}));
|
||||
|
||||
pendingAnimation.buildAnim().start();
|
||||
}
|
||||
@@ -4737,7 +4769,13 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
|
||||
|
||||
pendingAnimation.addEndListener(aBoolean -> {
|
||||
mSplitSelectStateController.launchSplitTasks(
|
||||
aBoolean1 -> RecentsView.this.resetFromSplitSelectionState());
|
||||
aBoolean1 -> {
|
||||
if (FeatureFlags.ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE.get()) {
|
||||
mSplitSelectStateController.resetState();
|
||||
} else {
|
||||
resetFromSplitSelectionState();
|
||||
}
|
||||
});
|
||||
InteractionJankMonitorWrapper.end(InteractionJankMonitorWrapper.CUJ_SPLIT_SCREEN_ENTER);
|
||||
});
|
||||
|
||||
@@ -4759,7 +4797,8 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
|
||||
|
||||
@SuppressLint("WrongCall")
|
||||
protected void resetFromSplitSelectionState() {
|
||||
if (mSplitSelectSource != null || mSplitHiddenTaskViewIndex != -1) {
|
||||
if (mSplitSelectSource != null || mSplitHiddenTaskViewIndex != -1 ||
|
||||
FeatureFlags.ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE.get()) {
|
||||
safeRemoveDragLayerView(mSplitSelectStateController.getFirstFloatingTaskView());
|
||||
safeRemoveDragLayerView(mSecondFloatingTaskView);
|
||||
safeRemoveDragLayerView(mSplitInstructionsView);
|
||||
@@ -4778,7 +4817,11 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
|
||||
setTaskViewsPrimarySplitTranslation(0);
|
||||
setTaskViewsSecondarySplitTranslation(0);
|
||||
|
||||
mSplitSelectStateController.resetState();
|
||||
if (!FeatureFlags.ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE.get()) {
|
||||
// When flag is on, this method gets called from resetState() call below, let's avoid
|
||||
// infinite recursion today
|
||||
mSplitSelectStateController.resetState();
|
||||
}
|
||||
if (mSplitHiddenTaskViewIndex == -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user