Loading quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java +2 −0 Original line number Diff line number Diff line Loading @@ -33,6 +33,7 @@ import static com.android.launcher3.LauncherState.OVERVIEW; import static com.android.launcher3.LauncherState.OVERVIEW_MODAL_TASK; import static com.android.launcher3.LauncherState.OVERVIEW_SPLIT_SELECT; import static com.android.launcher3.compat.AccessibilityManagerCompat.sendCustomAccessibilityEvent; import static com.android.launcher3.config.FeatureFlags.ENABLE_SPLIT_FROM_DESKTOP_TO_WORKSPACE; import static com.android.launcher3.config.FeatureFlags.ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE; import static com.android.launcher3.config.FeatureFlags.RECEIVE_UNFOLD_EVENTS_FROM_SYSUI; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_APP_LAUNCH_TAP; Loading Loading @@ -261,6 +262,7 @@ public class QuickstepLauncher extends Launcher { mDesktopVisibilityController = new DesktopVisibilityController(this); if (DesktopTaskView.DESKTOP_MODE_SUPPORTED) { mDesktopVisibilityController.registerSystemUiListener(); mSplitSelectStateController.initSplitFromDesktopController(this); } mHotseatPredictionController = new HotseatPredictionController(this); Loading quickstep/src/com/android/quickstep/SystemUiProxy.java +36 −0 Original line number Diff line number Diff line Loading @@ -84,6 +84,7 @@ import com.android.wm.shell.recents.IRecentTasks; import com.android.wm.shell.recents.IRecentTasksListener; import com.android.wm.shell.splitscreen.ISplitScreen; import com.android.wm.shell.splitscreen.ISplitScreenListener; import com.android.wm.shell.splitscreen.ISplitSelectListener; import com.android.wm.shell.startingsurface.IStartingWindow; import com.android.wm.shell.startingsurface.IStartingWindowListener; import com.android.wm.shell.transition.IShellTransitions; Loading Loading @@ -128,6 +129,7 @@ public class SystemUiProxy implements ISystemUiProxy { private IPipAnimationListener mPipAnimationListener; private IBubblesListener mBubblesListener; private ISplitScreenListener mSplitScreenListener; private ISplitSelectListener mSplitSelectListener; private IStartingWindowListener mStartingWindowListener; private ILauncherUnlockAnimationController mLauncherUnlockAnimationController; private IRecentTasksListener mRecentTasksListener; Loading Loading @@ -239,6 +241,7 @@ public class SystemUiProxy implements ISystemUiProxy { setPipAnimationListener(mPipAnimationListener); setBubblesListener(mBubblesListener); registerSplitScreenListener(mSplitScreenListener); registerSplitSelectListener(mSplitSelectListener); setStartingWindowListener(mStartingWindowListener); setLauncherUnlockAnimationController(mLauncherUnlockAnimationController); new LinkedHashMap<>(mRemoteTransitions).forEach(this::registerRemoteTransition); Loading Loading @@ -740,6 +743,28 @@ public class SystemUiProxy implements ISystemUiProxy { mSplitScreenListener = null; } public void registerSplitSelectListener(ISplitSelectListener listener) { if (mSplitScreen != null) { try { mSplitScreen.registerSplitSelectListener(listener); } catch (RemoteException e) { Log.w(TAG, "Failed call registerSplitSelectListener"); } } mSplitSelectListener = listener; } public void unregisterSplitSelectListener(ISplitSelectListener listener) { if (mSplitScreen != null) { try { mSplitScreen.unregisterSplitSelectListener(listener); } catch (RemoteException e) { Log.w(TAG, "Failed call unregisterSplitSelectListener"); } } mSplitSelectListener = null; } /** Start multiple tasks in split-screen simultaneously. */ public void startTasks(int taskId1, Bundle options1, int taskId2, Bundle options2, @SplitConfigurationOptions.StagePosition int splitPosition, float splitRatio, Loading Loading @@ -1281,6 +1306,17 @@ public class SystemUiProxy implements ISystemUiProxy { } } /** Perform cleanup transactions after animation to split select is complete */ public void onDesktopSplitSelectAnimComplete(ActivityManager.RunningTaskInfo taskInfo) { if (mDesktopMode != null) { try { mDesktopMode.onDesktopSplitSelectAnimComplete(taskInfo); } catch (RemoteException e) { Log.w(TAG, "Failed call onDesktopSplitSelectAnimComplete", e); } } } // // Unfold transition // Loading quickstep/src/com/android/quickstep/util/SplitSelectStateController.java +142 −0 Original line number Diff line number Diff line Loading @@ -17,10 +17,14 @@ package com.android.quickstep.util; import static com.android.launcher3.Utilities.postAsyncCallback; import static com.android.launcher3.config.FeatureFlags.ENABLE_SPLIT_FROM_DESKTOP_TO_WORKSPACE; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_DESKTOP_MODE_SPLIT_RIGHT_BOTTOM; import static com.android.launcher3.testing.shared.TestProtocol.LAUNCH_SPLIT_PAIR; import static com.android.launcher3.testing.shared.TestProtocol.testLogD; import static com.android.launcher3.util.Executors.MAIN_EXECUTOR; import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR; import static com.android.launcher3.util.SplitConfigurationOptions.DEFAULT_SPLIT_RATIO; import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_BOTTOM_OR_RIGHT; import static com.android.quickstep.util.SplitSelectDataHolder.SPLIT_PENDINGINTENT_PENDINGINTENT; import static com.android.quickstep.util.SplitSelectDataHolder.SPLIT_PENDINGINTENT_TASK; import static com.android.quickstep.util.SplitSelectDataHolder.SPLIT_SHORTCUT_TASK; Loading @@ -31,6 +35,8 @@ import static com.android.quickstep.util.SplitSelectDataHolder.SPLIT_TASK_PENDIN import static com.android.quickstep.util.SplitSelectDataHolder.SPLIT_TASK_SHORTCUT; import static com.android.quickstep.util.SplitSelectDataHolder.SPLIT_TASK_TASK; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.annotation.NonNull; import android.app.ActivityManager; import android.app.ActivityOptions; Loading @@ -38,11 +44,16 @@ import android.app.ActivityThread; import android.app.PendingIntent; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.content.pm.ShortcutInfo; import android.graphics.Rect; import android.graphics.RectF; import android.graphics.drawable.Drawable; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; import android.os.RemoteException; import android.os.SystemClock; import android.os.UserHandle; import android.util.Log; import android.util.Pair; Loading @@ -57,7 +68,11 @@ import android.window.TransitionInfo; import androidx.annotation.Nullable; import com.android.internal.logging.InstanceId; import com.android.launcher3.Launcher; import com.android.launcher3.R; import com.android.launcher3.anim.PendingAnimation; import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.icons.IconProvider; import com.android.launcher3.logging.StatsLogManager; import com.android.launcher3.model.data.ItemInfo; import com.android.launcher3.statehandlers.DepthController; Loading @@ -66,6 +81,11 @@ import com.android.launcher3.testing.TestLogging; import com.android.launcher3.testing.shared.TestProtocol; import com.android.launcher3.util.ComponentKey; import com.android.launcher3.util.SplitConfigurationOptions.StagePosition; import com.android.quickstep.OverviewComponentObserver; import com.android.quickstep.RecentsAnimationCallbacks; import com.android.quickstep.RecentsAnimationController; import com.android.quickstep.RecentsAnimationDeviceState; import com.android.quickstep.RecentsAnimationTargets; import com.android.quickstep.RecentsModel; import com.android.quickstep.SplitSelectionListener; import com.android.quickstep.SystemUiProxy; Loading @@ -74,8 +94,11 @@ import com.android.quickstep.TaskViewUtils; import com.android.quickstep.views.FloatingTaskView; import com.android.quickstep.views.GroupedTaskView; import com.android.quickstep.views.SplitInstructionsView; import com.android.quickstep.views.RecentsView; import com.android.systemui.shared.recents.model.Task; import com.android.systemui.shared.system.ActivityManagerWrapper; import com.android.systemui.shared.system.RemoteAnimationRunnerCompat; import com.android.wm.shell.splitscreen.ISplitSelectListener; import java.io.PrintWriter; import java.util.ArrayList; Loading @@ -99,6 +122,7 @@ public class SplitSelectStateController { private final StatsLogManager mStatsLogManager; private final SystemUiProxy mSystemUiProxy; private final StateManager mStateManager; private SplitFromDesktopController mSplitFromDesktopController; @Nullable private DepthController mDepthController; private boolean mRecentsAnimationRunning; Loading Loading @@ -476,6 +500,14 @@ public class SplitSelectStateController { } } public void initSplitFromDesktopController(Launcher launcher) { mSplitFromDesktopController = new SplitFromDesktopController(launcher); } public void enterSplitFromDesktop(ActivityManager.RunningTaskInfo taskInfo) { mSplitFromDesktopController.enterSplitSelect(taskInfo); } private RemoteTransition getShellRemoteTransition(int firstTaskId, int secondTaskId, @Nullable Consumer<Boolean> callback, String transitionName) { final RemoteSplitLaunchTransitionRunner animationRunner = Loading Loading @@ -686,4 +718,114 @@ public class SplitSelectStateController { mSplitSelectDataHolder.dump(prefix, writer); } } public class SplitFromDesktopController { private static final String TAG = "SplitFromDesktopController"; private final Launcher mLauncher; private final OverviewComponentObserver mOverviewComponentObserver; private final int mSplitPlaceholderSize; private final int mSplitPlaceholderInset; private ActivityManager.RunningTaskInfo mTaskInfo; private ISplitSelectListener mSplitSelectListener; private Drawable mAppIcon; public SplitFromDesktopController(Launcher launcher) { mLauncher = launcher; RecentsAnimationDeviceState deviceState = new RecentsAnimationDeviceState( launcher.getApplicationContext()); mOverviewComponentObserver = new OverviewComponentObserver(launcher.getApplicationContext(), deviceState); mSplitPlaceholderSize = mLauncher.getResources().getDimensionPixelSize( R.dimen.split_placeholder_size); mSplitPlaceholderInset = mLauncher.getResources().getDimensionPixelSize( R.dimen.split_placeholder_inset); mSplitSelectListener = new ISplitSelectListener.Stub() { @Override public boolean onRequestSplitSelect(ActivityManager.RunningTaskInfo taskInfo) { if (!ENABLE_SPLIT_FROM_DESKTOP_TO_WORKSPACE.get()) return false; MAIN_EXECUTOR.execute(() -> enterSplitSelect(taskInfo)); return true; } }; SystemUiProxy.INSTANCE.get(mLauncher).registerSplitSelectListener(mSplitSelectListener); } /** * Enter split select from desktop mode. * @param taskInfo the desktop task to move to split stage */ public void enterSplitSelect(ActivityManager.RunningTaskInfo taskInfo) { mTaskInfo = taskInfo; String packageName = mTaskInfo.realActivity.getPackageName(); PackageManager pm = mLauncher.getApplicationContext().getPackageManager(); IconProvider provider = new IconProvider(mLauncher.getApplicationContext()); try { mAppIcon = provider.getIcon(pm.getActivityInfo(mTaskInfo.baseActivity, PackageManager.ComponentInfoFlags.of(0))); } catch (PackageManager.NameNotFoundException e) { Log.w(TAG, "Package not found: " + packageName, e); } RecentsAnimationCallbacks callbacks = new RecentsAnimationCallbacks( SystemUiProxy.INSTANCE.get(mLauncher.getApplicationContext()), false /* allowMinimizeSplitScreen */); DesktopSplitRecentsAnimationListener listener = new DesktopSplitRecentsAnimationListener(); MAIN_EXECUTOR.execute(() -> { callbacks.addListener(listener); UI_HELPER_EXECUTOR.execute( // Transition from app to enter stage split in launcher with // recents animation. () -> ActivityManagerWrapper.getInstance().startRecentsActivity( mOverviewComponentObserver.getOverviewIntent(), SystemClock.uptimeMillis(), callbacks, null, null)); }); } private class DesktopSplitRecentsAnimationListener implements RecentsAnimationCallbacks.RecentsAnimationListener { private final Rect mTempRect = new Rect(); @Override public void onRecentsAnimationStart(RecentsAnimationController controller, RecentsAnimationTargets targets) { setInitialTaskSelect(mTaskInfo, STAGE_POSITION_BOTTOM_OR_RIGHT, null, LAUNCHER_DESKTOP_MODE_SPLIT_RIGHT_BOTTOM); RecentsView recentsView = mLauncher.getOverviewPanel(); recentsView.getPagedOrientationHandler().getInitialSplitPlaceholderBounds( mSplitPlaceholderSize, mSplitPlaceholderInset, mLauncher.getDeviceProfile(), getActiveSplitStagePosition(), mTempRect); PendingAnimation anim = new PendingAnimation( SplitAnimationTimings.TABLET_HOME_TO_SPLIT.getDuration()); RectF startingTaskRect = new RectF(mTaskInfo.configuration.windowConfiguration .getBounds()); final FloatingTaskView floatingTaskView = FloatingTaskView.getFloatingTaskView( mLauncher, mLauncher.getDragLayer(), null /* thumbnail */, mAppIcon, new RectF()); floatingTaskView.setAlpha(1); floatingTaskView.addStagingAnimation(anim, startingTaskRect, mTempRect, false /* fadeWithThumbnail */, true /* isStagedTask */); setFirstFloatingTaskView(floatingTaskView); anim.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationStart(Animator animation) { controller.finish(true /* toRecents */, null /* onFinishComplete */, false /* sendUserLeaveHint */); } @Override public void onAnimationEnd(Animator animation) { SystemUiProxy.INSTANCE.get(mLauncher.getApplicationContext()) .onDesktopSplitSelectAnimComplete(mTaskInfo); } }); anim.buildAnim().start(); } } } } quickstep/src/com/android/quickstep/util/SplitToWorkspaceController.java +3 −1 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package com.android.quickstep.util; import static com.android.launcher3.config.FeatureFlags.ENABLE_SPLIT_FROM_DESKTOP_TO_WORKSPACE; 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; Loading Loading @@ -178,7 +179,8 @@ public class SplitToWorkspaceController { private boolean shouldIgnoreSecondSplitLaunch() { return (!ENABLE_SPLIT_FROM_FULLSCREEN_WITH_KEYBOARD_SHORTCUTS.get() && !ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE.get()) && !ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE.get() && !ENABLE_SPLIT_FROM_DESKTOP_TO_WORKSPACE.get()) || !mController.isSplitSelectActive(); } } src/com/android/launcher3/config/FeatureFlags.java +4 −0 Original line number Diff line number Diff line Loading @@ -370,6 +370,10 @@ public final class FeatureFlags { 270393453, "ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE", TEAMFOOD, "Enable initiating split screen from workspace to workspace."); public static final BooleanFlag ENABLE_SPLIT_FROM_DESKTOP_TO_WORKSPACE = getDebugFlag( 279586624, "ENABLE_SPLIT_FROM_DESKTOP_TO_WORKSPACE", DISABLED, "Enable initiating split screen from desktop mode to workspace."); public static final BooleanFlag ENABLE_TRACKPAD_GESTURE = getDebugFlag(271010401, "ENABLE_TRACKPAD_GESTURE", ENABLED, "Enables trackpad gesture."); Loading Loading
quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java +2 −0 Original line number Diff line number Diff line Loading @@ -33,6 +33,7 @@ import static com.android.launcher3.LauncherState.OVERVIEW; import static com.android.launcher3.LauncherState.OVERVIEW_MODAL_TASK; import static com.android.launcher3.LauncherState.OVERVIEW_SPLIT_SELECT; import static com.android.launcher3.compat.AccessibilityManagerCompat.sendCustomAccessibilityEvent; import static com.android.launcher3.config.FeatureFlags.ENABLE_SPLIT_FROM_DESKTOP_TO_WORKSPACE; import static com.android.launcher3.config.FeatureFlags.ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE; import static com.android.launcher3.config.FeatureFlags.RECEIVE_UNFOLD_EVENTS_FROM_SYSUI; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_APP_LAUNCH_TAP; Loading Loading @@ -261,6 +262,7 @@ public class QuickstepLauncher extends Launcher { mDesktopVisibilityController = new DesktopVisibilityController(this); if (DesktopTaskView.DESKTOP_MODE_SUPPORTED) { mDesktopVisibilityController.registerSystemUiListener(); mSplitSelectStateController.initSplitFromDesktopController(this); } mHotseatPredictionController = new HotseatPredictionController(this); Loading
quickstep/src/com/android/quickstep/SystemUiProxy.java +36 −0 Original line number Diff line number Diff line Loading @@ -84,6 +84,7 @@ import com.android.wm.shell.recents.IRecentTasks; import com.android.wm.shell.recents.IRecentTasksListener; import com.android.wm.shell.splitscreen.ISplitScreen; import com.android.wm.shell.splitscreen.ISplitScreenListener; import com.android.wm.shell.splitscreen.ISplitSelectListener; import com.android.wm.shell.startingsurface.IStartingWindow; import com.android.wm.shell.startingsurface.IStartingWindowListener; import com.android.wm.shell.transition.IShellTransitions; Loading Loading @@ -128,6 +129,7 @@ public class SystemUiProxy implements ISystemUiProxy { private IPipAnimationListener mPipAnimationListener; private IBubblesListener mBubblesListener; private ISplitScreenListener mSplitScreenListener; private ISplitSelectListener mSplitSelectListener; private IStartingWindowListener mStartingWindowListener; private ILauncherUnlockAnimationController mLauncherUnlockAnimationController; private IRecentTasksListener mRecentTasksListener; Loading Loading @@ -239,6 +241,7 @@ public class SystemUiProxy implements ISystemUiProxy { setPipAnimationListener(mPipAnimationListener); setBubblesListener(mBubblesListener); registerSplitScreenListener(mSplitScreenListener); registerSplitSelectListener(mSplitSelectListener); setStartingWindowListener(mStartingWindowListener); setLauncherUnlockAnimationController(mLauncherUnlockAnimationController); new LinkedHashMap<>(mRemoteTransitions).forEach(this::registerRemoteTransition); Loading Loading @@ -740,6 +743,28 @@ public class SystemUiProxy implements ISystemUiProxy { mSplitScreenListener = null; } public void registerSplitSelectListener(ISplitSelectListener listener) { if (mSplitScreen != null) { try { mSplitScreen.registerSplitSelectListener(listener); } catch (RemoteException e) { Log.w(TAG, "Failed call registerSplitSelectListener"); } } mSplitSelectListener = listener; } public void unregisterSplitSelectListener(ISplitSelectListener listener) { if (mSplitScreen != null) { try { mSplitScreen.unregisterSplitSelectListener(listener); } catch (RemoteException e) { Log.w(TAG, "Failed call unregisterSplitSelectListener"); } } mSplitSelectListener = null; } /** Start multiple tasks in split-screen simultaneously. */ public void startTasks(int taskId1, Bundle options1, int taskId2, Bundle options2, @SplitConfigurationOptions.StagePosition int splitPosition, float splitRatio, Loading Loading @@ -1281,6 +1306,17 @@ public class SystemUiProxy implements ISystemUiProxy { } } /** Perform cleanup transactions after animation to split select is complete */ public void onDesktopSplitSelectAnimComplete(ActivityManager.RunningTaskInfo taskInfo) { if (mDesktopMode != null) { try { mDesktopMode.onDesktopSplitSelectAnimComplete(taskInfo); } catch (RemoteException e) { Log.w(TAG, "Failed call onDesktopSplitSelectAnimComplete", e); } } } // // Unfold transition // Loading
quickstep/src/com/android/quickstep/util/SplitSelectStateController.java +142 −0 Original line number Diff line number Diff line Loading @@ -17,10 +17,14 @@ package com.android.quickstep.util; import static com.android.launcher3.Utilities.postAsyncCallback; import static com.android.launcher3.config.FeatureFlags.ENABLE_SPLIT_FROM_DESKTOP_TO_WORKSPACE; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_DESKTOP_MODE_SPLIT_RIGHT_BOTTOM; import static com.android.launcher3.testing.shared.TestProtocol.LAUNCH_SPLIT_PAIR; import static com.android.launcher3.testing.shared.TestProtocol.testLogD; import static com.android.launcher3.util.Executors.MAIN_EXECUTOR; import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR; import static com.android.launcher3.util.SplitConfigurationOptions.DEFAULT_SPLIT_RATIO; import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_BOTTOM_OR_RIGHT; import static com.android.quickstep.util.SplitSelectDataHolder.SPLIT_PENDINGINTENT_PENDINGINTENT; import static com.android.quickstep.util.SplitSelectDataHolder.SPLIT_PENDINGINTENT_TASK; import static com.android.quickstep.util.SplitSelectDataHolder.SPLIT_SHORTCUT_TASK; Loading @@ -31,6 +35,8 @@ import static com.android.quickstep.util.SplitSelectDataHolder.SPLIT_TASK_PENDIN import static com.android.quickstep.util.SplitSelectDataHolder.SPLIT_TASK_SHORTCUT; import static com.android.quickstep.util.SplitSelectDataHolder.SPLIT_TASK_TASK; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.annotation.NonNull; import android.app.ActivityManager; import android.app.ActivityOptions; Loading @@ -38,11 +44,16 @@ import android.app.ActivityThread; import android.app.PendingIntent; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.content.pm.ShortcutInfo; import android.graphics.Rect; import android.graphics.RectF; import android.graphics.drawable.Drawable; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; import android.os.RemoteException; import android.os.SystemClock; import android.os.UserHandle; import android.util.Log; import android.util.Pair; Loading @@ -57,7 +68,11 @@ import android.window.TransitionInfo; import androidx.annotation.Nullable; import com.android.internal.logging.InstanceId; import com.android.launcher3.Launcher; import com.android.launcher3.R; import com.android.launcher3.anim.PendingAnimation; import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.icons.IconProvider; import com.android.launcher3.logging.StatsLogManager; import com.android.launcher3.model.data.ItemInfo; import com.android.launcher3.statehandlers.DepthController; Loading @@ -66,6 +81,11 @@ import com.android.launcher3.testing.TestLogging; import com.android.launcher3.testing.shared.TestProtocol; import com.android.launcher3.util.ComponentKey; import com.android.launcher3.util.SplitConfigurationOptions.StagePosition; import com.android.quickstep.OverviewComponentObserver; import com.android.quickstep.RecentsAnimationCallbacks; import com.android.quickstep.RecentsAnimationController; import com.android.quickstep.RecentsAnimationDeviceState; import com.android.quickstep.RecentsAnimationTargets; import com.android.quickstep.RecentsModel; import com.android.quickstep.SplitSelectionListener; import com.android.quickstep.SystemUiProxy; Loading @@ -74,8 +94,11 @@ import com.android.quickstep.TaskViewUtils; import com.android.quickstep.views.FloatingTaskView; import com.android.quickstep.views.GroupedTaskView; import com.android.quickstep.views.SplitInstructionsView; import com.android.quickstep.views.RecentsView; import com.android.systemui.shared.recents.model.Task; import com.android.systemui.shared.system.ActivityManagerWrapper; import com.android.systemui.shared.system.RemoteAnimationRunnerCompat; import com.android.wm.shell.splitscreen.ISplitSelectListener; import java.io.PrintWriter; import java.util.ArrayList; Loading @@ -99,6 +122,7 @@ public class SplitSelectStateController { private final StatsLogManager mStatsLogManager; private final SystemUiProxy mSystemUiProxy; private final StateManager mStateManager; private SplitFromDesktopController mSplitFromDesktopController; @Nullable private DepthController mDepthController; private boolean mRecentsAnimationRunning; Loading Loading @@ -476,6 +500,14 @@ public class SplitSelectStateController { } } public void initSplitFromDesktopController(Launcher launcher) { mSplitFromDesktopController = new SplitFromDesktopController(launcher); } public void enterSplitFromDesktop(ActivityManager.RunningTaskInfo taskInfo) { mSplitFromDesktopController.enterSplitSelect(taskInfo); } private RemoteTransition getShellRemoteTransition(int firstTaskId, int secondTaskId, @Nullable Consumer<Boolean> callback, String transitionName) { final RemoteSplitLaunchTransitionRunner animationRunner = Loading Loading @@ -686,4 +718,114 @@ public class SplitSelectStateController { mSplitSelectDataHolder.dump(prefix, writer); } } public class SplitFromDesktopController { private static final String TAG = "SplitFromDesktopController"; private final Launcher mLauncher; private final OverviewComponentObserver mOverviewComponentObserver; private final int mSplitPlaceholderSize; private final int mSplitPlaceholderInset; private ActivityManager.RunningTaskInfo mTaskInfo; private ISplitSelectListener mSplitSelectListener; private Drawable mAppIcon; public SplitFromDesktopController(Launcher launcher) { mLauncher = launcher; RecentsAnimationDeviceState deviceState = new RecentsAnimationDeviceState( launcher.getApplicationContext()); mOverviewComponentObserver = new OverviewComponentObserver(launcher.getApplicationContext(), deviceState); mSplitPlaceholderSize = mLauncher.getResources().getDimensionPixelSize( R.dimen.split_placeholder_size); mSplitPlaceholderInset = mLauncher.getResources().getDimensionPixelSize( R.dimen.split_placeholder_inset); mSplitSelectListener = new ISplitSelectListener.Stub() { @Override public boolean onRequestSplitSelect(ActivityManager.RunningTaskInfo taskInfo) { if (!ENABLE_SPLIT_FROM_DESKTOP_TO_WORKSPACE.get()) return false; MAIN_EXECUTOR.execute(() -> enterSplitSelect(taskInfo)); return true; } }; SystemUiProxy.INSTANCE.get(mLauncher).registerSplitSelectListener(mSplitSelectListener); } /** * Enter split select from desktop mode. * @param taskInfo the desktop task to move to split stage */ public void enterSplitSelect(ActivityManager.RunningTaskInfo taskInfo) { mTaskInfo = taskInfo; String packageName = mTaskInfo.realActivity.getPackageName(); PackageManager pm = mLauncher.getApplicationContext().getPackageManager(); IconProvider provider = new IconProvider(mLauncher.getApplicationContext()); try { mAppIcon = provider.getIcon(pm.getActivityInfo(mTaskInfo.baseActivity, PackageManager.ComponentInfoFlags.of(0))); } catch (PackageManager.NameNotFoundException e) { Log.w(TAG, "Package not found: " + packageName, e); } RecentsAnimationCallbacks callbacks = new RecentsAnimationCallbacks( SystemUiProxy.INSTANCE.get(mLauncher.getApplicationContext()), false /* allowMinimizeSplitScreen */); DesktopSplitRecentsAnimationListener listener = new DesktopSplitRecentsAnimationListener(); MAIN_EXECUTOR.execute(() -> { callbacks.addListener(listener); UI_HELPER_EXECUTOR.execute( // Transition from app to enter stage split in launcher with // recents animation. () -> ActivityManagerWrapper.getInstance().startRecentsActivity( mOverviewComponentObserver.getOverviewIntent(), SystemClock.uptimeMillis(), callbacks, null, null)); }); } private class DesktopSplitRecentsAnimationListener implements RecentsAnimationCallbacks.RecentsAnimationListener { private final Rect mTempRect = new Rect(); @Override public void onRecentsAnimationStart(RecentsAnimationController controller, RecentsAnimationTargets targets) { setInitialTaskSelect(mTaskInfo, STAGE_POSITION_BOTTOM_OR_RIGHT, null, LAUNCHER_DESKTOP_MODE_SPLIT_RIGHT_BOTTOM); RecentsView recentsView = mLauncher.getOverviewPanel(); recentsView.getPagedOrientationHandler().getInitialSplitPlaceholderBounds( mSplitPlaceholderSize, mSplitPlaceholderInset, mLauncher.getDeviceProfile(), getActiveSplitStagePosition(), mTempRect); PendingAnimation anim = new PendingAnimation( SplitAnimationTimings.TABLET_HOME_TO_SPLIT.getDuration()); RectF startingTaskRect = new RectF(mTaskInfo.configuration.windowConfiguration .getBounds()); final FloatingTaskView floatingTaskView = FloatingTaskView.getFloatingTaskView( mLauncher, mLauncher.getDragLayer(), null /* thumbnail */, mAppIcon, new RectF()); floatingTaskView.setAlpha(1); floatingTaskView.addStagingAnimation(anim, startingTaskRect, mTempRect, false /* fadeWithThumbnail */, true /* isStagedTask */); setFirstFloatingTaskView(floatingTaskView); anim.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationStart(Animator animation) { controller.finish(true /* toRecents */, null /* onFinishComplete */, false /* sendUserLeaveHint */); } @Override public void onAnimationEnd(Animator animation) { SystemUiProxy.INSTANCE.get(mLauncher.getApplicationContext()) .onDesktopSplitSelectAnimComplete(mTaskInfo); } }); anim.buildAnim().start(); } } } }
quickstep/src/com/android/quickstep/util/SplitToWorkspaceController.java +3 −1 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package com.android.quickstep.util; import static com.android.launcher3.config.FeatureFlags.ENABLE_SPLIT_FROM_DESKTOP_TO_WORKSPACE; 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; Loading Loading @@ -178,7 +179,8 @@ public class SplitToWorkspaceController { private boolean shouldIgnoreSecondSplitLaunch() { return (!ENABLE_SPLIT_FROM_FULLSCREEN_WITH_KEYBOARD_SHORTCUTS.get() && !ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE.get()) && !ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE.get() && !ENABLE_SPLIT_FROM_DESKTOP_TO_WORKSPACE.get()) || !mController.isSplitSelectActive(); } }
src/com/android/launcher3/config/FeatureFlags.java +4 −0 Original line number Diff line number Diff line Loading @@ -370,6 +370,10 @@ public final class FeatureFlags { 270393453, "ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE", TEAMFOOD, "Enable initiating split screen from workspace to workspace."); public static final BooleanFlag ENABLE_SPLIT_FROM_DESKTOP_TO_WORKSPACE = getDebugFlag( 279586624, "ENABLE_SPLIT_FROM_DESKTOP_TO_WORKSPACE", DISABLED, "Enable initiating split screen from desktop mode to workspace."); public static final BooleanFlag ENABLE_TRACKPAD_GESTURE = getDebugFlag(271010401, "ENABLE_TRACKPAD_GESTURE", ENABLED, "Enables trackpad gesture."); Loading