diff --git a/quickstep/src/com/android/launcher3/uioverrides/BaseRecentsViewStateController.java b/quickstep/src/com/android/launcher3/uioverrides/BaseRecentsViewStateController.java index 8c8e267e34..d241260082 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/BaseRecentsViewStateController.java +++ b/quickstep/src/com/android/launcher3/uioverrides/BaseRecentsViewStateController.java @@ -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 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) { diff --git a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java index ecc8e196fd..6507dfe929 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java +++ b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java @@ -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 diff --git a/quickstep/src/com/android/quickstep/SplitSelectionListener.kt b/quickstep/src/com/android/quickstep/SplitSelectionListener.kt new file mode 100644 index 0000000000..5025c1c181 --- /dev/null +++ b/quickstep/src/com/android/quickstep/SplitSelectionListener.kt @@ -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) { + } +} \ No newline at end of file diff --git a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java index 074aedd3c7..45930446b1 100644 --- a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java +++ b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java @@ -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 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; diff --git a/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java b/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java index 4dbf4e3655..2ac73c83c2 100644 --- a/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java +++ b/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java @@ -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 - 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 { 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