diff options
10 files changed, 86 insertions, 30 deletions
diff --git a/core/java/com/android/internal/statusbar/IStatusBar.aidl b/core/java/com/android/internal/statusbar/IStatusBar.aidl index 6ffc63869f26..a2efbd29c54a 100644 --- a/core/java/com/android/internal/statusbar/IStatusBar.aidl +++ b/core/java/com/android/internal/statusbar/IStatusBar.aidl @@ -370,9 +370,10 @@ oneway interface IStatusBar /** * Enters stage split from a current running app. * + * @param displayId the id of the current display. * @param leftOrTop indicates where the stage split is. */ - void enterStageSplitFromRunningApp(boolean leftOrTop); + void moveFocusedTaskToStageSplit(int displayId, boolean leftOrTop); /** * Shows the media output switcher dialog. diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopMode.java b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopMode.java index 1071d728a56d..838603f80cf1 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopMode.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopMode.java @@ -53,4 +53,7 @@ public interface DesktopMode { /** Called when requested to go to fullscreen from the current focused desktop app. */ void moveFocusedTaskToFullscreen(int displayId); + + /** Called when requested to go to split screen from the current focused desktop app. */ + void moveFocusedTaskToStageSplit(int displayId, boolean leftOrTop); } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt index 654409f4a637..6f2f209c7816 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt @@ -62,6 +62,7 @@ import com.android.wm.shell.common.SyncTransactionQueue import com.android.wm.shell.common.annotations.ExternalThread import com.android.wm.shell.common.annotations.ShellMainThread import com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT +import com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT import com.android.wm.shell.desktopmode.DesktopModeTaskRepository.VisibleTasksListener import com.android.wm.shell.desktopmode.DragToDesktopTransitionHandler.DragToDesktopStateListener import com.android.wm.shell.draganddrop.DragAndDropController @@ -382,14 +383,8 @@ class DesktopTasksController( /** Enter fullscreen by moving the focused freeform task in given `displayId` to fullscreen. */ fun enterFullscreen(displayId: Int) { - if (DesktopModeStatus.isEnabled()) { - shellTaskOrganizer - .getRunningTasks(displayId) - .find { taskInfo -> - taskInfo.isFocused && taskInfo.windowingMode == WINDOWING_MODE_FREEFORM - } - ?.let { moveToFullscreenWithAnimation(it, it.positionInParent) } - } + getFocusedFreeformTask(displayId) + ?.let { moveToFullscreenWithAnimation(it, it.positionInParent) } } /** Move a desktop app to split screen. */ @@ -870,12 +865,28 @@ class DesktopTasksController( wct.setDensityDpi(taskInfo.token, getDefaultDensityDpi()) } + /** Enter split by using the focused desktop task in given `displayId`. */ + fun enterSplit( + displayId: Int, + leftOrTop: Boolean + ) { + getFocusedFreeformTask(displayId)?.let { requestSplit(it, leftOrTop) } + } + + private fun getFocusedFreeformTask(displayId: Int): RunningTaskInfo? { + return shellTaskOrganizer.getRunningTasks(displayId) + .find { taskInfo -> taskInfo.isFocused && + taskInfo.windowingMode == WINDOWING_MODE_FREEFORM } + } + /** * Requests a task be transitioned from desktop to split select. Applies needed windowing * changes if this transition is enabled. */ + @JvmOverloads fun requestSplit( - taskInfo: RunningTaskInfo + taskInfo: RunningTaskInfo, + leftOrTop: Boolean = false, ) { val windowingMode = taskInfo.windowingMode if (windowingMode == WINDOWING_MODE_FULLSCREEN || windowingMode == WINDOWING_MODE_FREEFORM @@ -883,7 +894,8 @@ class DesktopTasksController( val wct = WindowContainerTransaction() addMoveToSplitChanges(wct, taskInfo) splitScreenController.requestEnterSplitSelect(taskInfo, wct, - SPLIT_POSITION_BOTTOM_OR_RIGHT, taskInfo.configuration.windowConfiguration.bounds) + if (leftOrTop) SPLIT_POSITION_TOP_OR_LEFT else SPLIT_POSITION_BOTTOM_OR_RIGHT, + taskInfo.configuration.windowConfiguration.bounds) } } @@ -1134,6 +1146,12 @@ class DesktopTasksController( this@DesktopTasksController.enterFullscreen(displayId) } } + + override fun moveFocusedTaskToStageSplit(displayId: Int, leftOrTop: Boolean) { + mainExecutor.execute { + this@DesktopTasksController.enterSplit(displayId, leftOrTop) + } + } } /** The interface for calls from outside the host process. */ diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt index 35c803b78674..c31dfd055efb 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt @@ -51,6 +51,7 @@ import com.android.wm.shell.common.LaunchAdjacentController import com.android.wm.shell.common.MultiInstanceHelper import com.android.wm.shell.common.ShellExecutor import com.android.wm.shell.common.SyncTransactionQueue +import com.android.wm.shell.common.split.SplitScreenConstants import com.android.wm.shell.desktopmode.DesktopTestHelpers.Companion.createFreeformTask import com.android.wm.shell.desktopmode.DesktopTestHelpers.Companion.createFullscreenTask import com.android.wm.shell.desktopmode.DesktopTestHelpers.Companion.createHomeTask @@ -798,6 +799,22 @@ class DesktopTasksControllerTest : ShellTestCase() { .isEqualTo(WINDOWING_MODE_FULLSCREEN) } + fun enterSplit_freeformTaskIsMovedToSplit() { + val task1 = setUpFreeformTask() + val task2 = setUpFreeformTask() + val task3 = setUpFreeformTask() + + task1.isFocused = false + task2.isFocused = true + task3.isFocused = false + + controller.enterSplit(DEFAULT_DISPLAY, false) + + verify(splitScreenController).requestEnterSplitSelect(task2, any(), + SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT, + task2.configuration.windowConfiguration.bounds) + } + private fun setUpFreeformTask(displayId: Int = DEFAULT_DISPLAY): RunningTaskInfo { val task = createFreeformTask(displayId) whenever(shellTaskOrganizer.getRunningTaskInfo(task.taskId)).thenReturn(task) diff --git a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java index 5f8b5ddc9de6..d0ff33869a77 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java +++ b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java @@ -33,6 +33,7 @@ import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_A import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_BOUNCER_SHOWING; import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_DEVICE_DOZING; import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_DEVICE_DREAMING; +import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_FREEFORM_ACTIVE_IN_DESKTOP_MODE; import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_STATUS_BAR_KEYGUARD_GOING_AWAY; import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING; import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING_OCCLUDED; @@ -111,6 +112,7 @@ import com.android.systemui.statusbar.NotificationShadeWindowController; import com.android.systemui.statusbar.phone.StatusBarWindowCallback; import com.android.systemui.statusbar.policy.CallbackController; import com.android.systemui.unfold.progress.UnfoldTransitionProgressForwarder; +import com.android.wm.shell.desktopmode.DesktopModeStatus; import com.android.wm.shell.sysui.ShellInterface; import dagger.Lazy; @@ -673,9 +675,13 @@ public class OverviewProxyService implements CallbackController<OverviewProxyLis } @Override - public void enterStageSplitFromRunningApp(boolean leftOrTop) { + public void moveFocusedTaskToStageSplit(int displayId, boolean leftOrTop) { if (mOverviewProxy != null) { try { + if (DesktopModeStatus.isEnabled() && (sysUiState.getFlags() + & SYSUI_STATE_FREEFORM_ACTIVE_IN_DESKTOP_MODE) != 0) { + return; + } mOverviewProxy.enterStageSplitFromRunningApp(leftOrTop); } catch (RemoteException e) { Log.w(TAG_OPS, "Unable to enter stage split from the current running app"); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java index bb8168335b60..4275fc6f4097 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java @@ -169,7 +169,7 @@ public class CommandQueue extends IStatusBar.Stub implements private static final int MSG_TILE_SERVICE_REQUEST_LISTENING_STATE = 68 << MSG_SHIFT; private static final int MSG_SHOW_REAR_DISPLAY_DIALOG = 69 << MSG_SHIFT; private static final int MSG_MOVE_FOCUSED_TASK_TO_FULLSCREEN = 70 << MSG_SHIFT; - private static final int MSG_ENTER_STAGE_SPLIT_FROM_RUNNING_APP = 71 << MSG_SHIFT; + private static final int MSG_MOVE_FOCUSED_TASK_TO_STAGE_SPLIT = 71 << MSG_SHIFT; private static final int MSG_SHOW_MEDIA_OUTPUT_SWITCHER = 72 << MSG_SHIFT; private static final int MSG_TOGGLE_TASKBAR = 73 << MSG_SHIFT; private static final int MSG_SETTING_CHANGED = 74 << MSG_SHIFT; @@ -503,9 +503,9 @@ public class CommandQueue extends IStatusBar.Stub implements default void moveFocusedTaskToFullscreen(int displayId) {} /** - * @see IStatusBar#enterStageSplitFromRunningApp + * @see IStatusBar#moveFocusedTaskToStageSplit */ - default void enterStageSplitFromRunningApp(boolean leftOrTop) {} + default void moveFocusedTaskToStageSplit(int displayId, boolean leftOrTop) {} /** * @see IStatusBar#showMediaOutputSwitcher @@ -1338,10 +1338,13 @@ public class CommandQueue extends IStatusBar.Stub implements } @Override - public void enterStageSplitFromRunningApp(boolean leftOrTop) { + public void moveFocusedTaskToStageSplit(int displayId, boolean leftOrTop) { synchronized (mLock) { - mHandler.obtainMessage(MSG_ENTER_STAGE_SPLIT_FROM_RUNNING_APP, - leftOrTop).sendToTarget(); + SomeArgs args = SomeArgs.obtain(); + args.argi1 = displayId; + args.argi2 = leftOrTop ? 1 : 0; + mHandler.obtainMessage(MSG_MOVE_FOCUSED_TASK_TO_STAGE_SPLIT, + args).sendToTarget(); } } @@ -1907,11 +1910,15 @@ public class CommandQueue extends IStatusBar.Stub implements } break; } - case MSG_ENTER_STAGE_SPLIT_FROM_RUNNING_APP: + case MSG_MOVE_FOCUSED_TASK_TO_STAGE_SPLIT: { + args = (SomeArgs) msg.obj; + int displayId = args.argi1; + boolean leftOrTop = args.argi2 != 0; for (int i = 0; i < mCallbacks.size(); i++) { - mCallbacks.get(i).enterStageSplitFromRunningApp((Boolean) msg.obj); + mCallbacks.get(i).moveFocusedTaskToStageSplit(displayId, leftOrTop); } break; + } case MSG_SHOW_MEDIA_OUTPUT_SWITCHER: args = (SomeArgs) msg.obj; String clientPackageName = (String) args.arg1; diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java b/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java index 324d723207cd..7674fe988255 100644 --- a/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java +++ b/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java @@ -361,12 +361,14 @@ public final class WMShell implements public void enterDesktop(int displayId) { desktopMode.enterDesktop(displayId); } - }); - mCommandQueue.addCallback(new CommandQueue.Callbacks() { @Override public void moveFocusedTaskToFullscreen(int displayId) { desktopMode.moveFocusedTaskToFullscreen(displayId); } + @Override + public void moveFocusedTaskToStageSplit(int displayId, boolean leftOrTop) { + desktopMode.moveFocusedTaskToStageSplit(displayId, leftOrTop); + } }); } diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java index ec4b38b10af2..5974ac8bd41b 100644 --- a/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -3523,7 +3523,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { case KeyEvent.KEYCODE_DPAD_LEFT: if (firstDown && event.isMetaPressed()) { if (event.isCtrlPressed()) { - enterStageSplitFromRunningApp(true /* leftOrTop */); + moveFocusedTaskToStageSplit(getTargetDisplayIdForKeyEvent(event), + true /* leftOrTop */); logKeyboardSystemsEvent(event, KeyboardLogEvent.SPLIT_SCREEN_NAVIGATION); } else { logKeyboardSystemsEvent(event, KeyboardLogEvent.BACK); @@ -3534,7 +3535,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { break; case KeyEvent.KEYCODE_DPAD_RIGHT: if (firstDown && event.isMetaPressed() && event.isCtrlPressed()) { - enterStageSplitFromRunningApp(false /* leftOrTop */); + moveFocusedTaskToStageSplit(getTargetDisplayIdForKeyEvent(event), + false /* leftOrTop */); logKeyboardSystemsEvent(event, KeyboardLogEvent.SPLIT_SCREEN_NAVIGATION); return true; } @@ -4387,10 +4389,10 @@ public class PhoneWindowManager implements WindowManagerPolicy { } } - private void enterStageSplitFromRunningApp(boolean leftOrTop) { + private void moveFocusedTaskToStageSplit(int displayId, boolean leftOrTop) { StatusBarManagerInternal statusbar = getStatusBarManagerInternal(); if (statusbar != null) { - statusbar.enterStageSplitFromRunningApp(leftOrTop); + statusbar.moveFocusedTaskToStageSplit(displayId, leftOrTop); } } diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java b/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java index 14e0ce1704c8..c73f89c4731e 100644 --- a/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java +++ b/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java @@ -233,9 +233,9 @@ public interface StatusBarManagerInternal { /** * Enters stage split from a current running app. * - * @see com.android.internal.statusbar.IStatusBar#enterStageSplitFromRunningApp + * @see com.android.internal.statusbar.IStatusBar#moveFocusedTaskToStageSplit */ - void enterStageSplitFromRunningApp(boolean leftOrTop); + void moveFocusedTaskToStageSplit(int displayId, boolean leftOrTop); /** * Shows the media output switcher dialog. diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java index 0b48a75298a4..214dbe01aee5 100644 --- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java +++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java @@ -820,11 +820,11 @@ public class StatusBarManagerService extends IStatusBarService.Stub implements D } @Override - public void enterStageSplitFromRunningApp(boolean leftOrTop) { + public void moveFocusedTaskToStageSplit(int displayId, boolean leftOrTop) { IStatusBar bar = mBar; if (bar != null) { try { - bar.enterStageSplitFromRunningApp(leftOrTop); + bar.moveFocusedTaskToStageSplit(displayId, leftOrTop); } catch (RemoteException ex) { } } } |