Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9f049e6d authored by Orhan Uysal's avatar Orhan Uysal
Browse files

Add a keyboard shortcut for desktop to split.

Similar to fullscreen to split, ctrl + action + L/R should bring the
focused freeform window to split side stage.

Test: atest DesktopTasksController
Test: Manually trigger the shortcut to move it to split
Bug: 326062194
Flag: ACONFIG com.android.window.flags.enable_desktop_windowing_mode DEVELOPMENT
Change-Id: I459fc2fa00b821c279fa77e3616001e44dd32d58

Change-Id: I25a31a1ab49951a313f62184208ebdf6613ac557
parent 4e62d6c3
Loading
Loading
Loading
Loading
+2 −1
Original line number Original line Diff line number Diff line
@@ -370,9 +370,10 @@ oneway interface IStatusBar
    /**
    /**
     * Enters stage split from a current running app.
     * Enters stage split from a current running app.
     *
     *
     * @param displayId the id of the current display.
     * @param leftOrTop indicates where the stage split is.
     * @param leftOrTop indicates where the stage split is.
     */
     */
    void enterStageSplitFromRunningApp(boolean leftOrTop);
    void moveFocusedTaskToStageSplit(int displayId, boolean leftOrTop);


    /**
    /**
     * Shows the media output switcher dialog.
     * Shows the media output switcher dialog.
+3 −0
Original line number Original line Diff line number Diff line
@@ -53,4 +53,7 @@ public interface DesktopMode {


    /** Called when requested to go to fullscreen from the current focused desktop app. */
    /** Called when requested to go to fullscreen from the current focused desktop app. */
    void moveFocusedTaskToFullscreen(int displayId);
    void moveFocusedTaskToFullscreen(int displayId);

    /** Called when requested to go to split screen from the current focused desktop app. */
    void moveFocusedTaskToStageSplit(int displayId, boolean leftOrTop);
}
}
+28 −10
Original line number Original line Diff line number Diff line
@@ -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.ExternalThread
import com.android.wm.shell.common.annotations.ShellMainThread
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_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.DesktopModeTaskRepository.VisibleTasksListener
import com.android.wm.shell.desktopmode.DragToDesktopTransitionHandler.DragToDesktopStateListener
import com.android.wm.shell.desktopmode.DragToDesktopTransitionHandler.DragToDesktopStateListener
import com.android.wm.shell.draganddrop.DragAndDropController
import com.android.wm.shell.draganddrop.DragAndDropController
@@ -382,15 +383,9 @@ class DesktopTasksController(


    /** Enter fullscreen by moving the focused freeform task in given `displayId` to fullscreen. */
    /** Enter fullscreen by moving the focused freeform task in given `displayId` to fullscreen. */
    fun enterFullscreen(displayId: Int) {
    fun enterFullscreen(displayId: Int) {
        if (DesktopModeStatus.isEnabled()) {
        getFocusedFreeformTask(displayId)
            shellTaskOrganizer
                    .getRunningTasks(displayId)
                    .find { taskInfo ->
                        taskInfo.isFocused && taskInfo.windowingMode == WINDOWING_MODE_FREEFORM
                    }
                ?.let { moveToFullscreenWithAnimation(it, it.positionInParent) }
                ?.let { moveToFullscreenWithAnimation(it, it.positionInParent) }
    }
    }
    }


    /** Move a desktop app to split screen. */
    /** Move a desktop app to split screen. */
    fun moveToSplit(task: RunningTaskInfo) {
    fun moveToSplit(task: RunningTaskInfo) {
@@ -870,12 +865,28 @@ class DesktopTasksController(
        wct.setDensityDpi(taskInfo.token, getDefaultDensityDpi())
        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
     * Requests a task be transitioned from desktop to split select. Applies needed windowing
     * changes if this transition is enabled.
     * changes if this transition is enabled.
     */
     */
    @JvmOverloads
    fun requestSplit(
    fun requestSplit(
        taskInfo: RunningTaskInfo
        taskInfo: RunningTaskInfo,
        leftOrTop: Boolean = false,
    ) {
    ) {
        val windowingMode = taskInfo.windowingMode
        val windowingMode = taskInfo.windowingMode
        if (windowingMode == WINDOWING_MODE_FULLSCREEN || windowingMode == WINDOWING_MODE_FREEFORM
        if (windowingMode == WINDOWING_MODE_FULLSCREEN || windowingMode == WINDOWING_MODE_FREEFORM
@@ -883,7 +894,8 @@ class DesktopTasksController(
            val wct = WindowContainerTransaction()
            val wct = WindowContainerTransaction()
            addMoveToSplitChanges(wct, taskInfo)
            addMoveToSplitChanges(wct, taskInfo)
            splitScreenController.requestEnterSplitSelect(taskInfo, wct,
            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)
                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. */
    /** The interface for calls from outside the host process. */
+17 −0
Original line number Original line Diff line number Diff line
@@ -51,6 +51,7 @@ import com.android.wm.shell.common.LaunchAdjacentController
import com.android.wm.shell.common.MultiInstanceHelper
import com.android.wm.shell.common.MultiInstanceHelper
import com.android.wm.shell.common.ShellExecutor
import com.android.wm.shell.common.ShellExecutor
import com.android.wm.shell.common.SyncTransactionQueue
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.createFreeformTask
import com.android.wm.shell.desktopmode.DesktopTestHelpers.Companion.createFullscreenTask
import com.android.wm.shell.desktopmode.DesktopTestHelpers.Companion.createFullscreenTask
import com.android.wm.shell.desktopmode.DesktopTestHelpers.Companion.createHomeTask
import com.android.wm.shell.desktopmode.DesktopTestHelpers.Companion.createHomeTask
@@ -798,6 +799,22 @@ class DesktopTasksControllerTest : ShellTestCase() {
                .isEqualTo(WINDOWING_MODE_FULLSCREEN)
                .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 {
    private fun setUpFreeformTask(displayId: Int = DEFAULT_DISPLAY): RunningTaskInfo {
        val task = createFreeformTask(displayId)
        val task = createFreeformTask(displayId)
        whenever(shellTaskOrganizer.getRunningTaskInfo(task.taskId)).thenReturn(task)
        whenever(shellTaskOrganizer.getRunningTaskInfo(task.taskId)).thenReturn(task)
+7 −1
Original line number Original line Diff line number Diff line
@@ -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_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_DOZING;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_DEVICE_DREAMING;
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_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;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING_OCCLUDED;
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.phone.StatusBarWindowCallback;
import com.android.systemui.statusbar.policy.CallbackController;
import com.android.systemui.statusbar.policy.CallbackController;
import com.android.systemui.unfold.progress.UnfoldTransitionProgressForwarder;
import com.android.systemui.unfold.progress.UnfoldTransitionProgressForwarder;
import com.android.wm.shell.desktopmode.DesktopModeStatus;
import com.android.wm.shell.sysui.ShellInterface;
import com.android.wm.shell.sysui.ShellInterface;


import dagger.Lazy;
import dagger.Lazy;
@@ -673,9 +675,13 @@ public class OverviewProxyService implements CallbackController<OverviewProxyLis
            }
            }


            @Override
            @Override
            public void enterStageSplitFromRunningApp(boolean leftOrTop) {
            public void moveFocusedTaskToStageSplit(int displayId, boolean leftOrTop) {
                if (mOverviewProxy != null) {
                if (mOverviewProxy != null) {
                    try {
                    try {
                        if (DesktopModeStatus.isEnabled() && (sysUiState.getFlags()
                                & SYSUI_STATE_FREEFORM_ACTIVE_IN_DESKTOP_MODE) != 0) {
                            return;
                        }
                        mOverviewProxy.enterStageSplitFromRunningApp(leftOrTop);
                        mOverviewProxy.enterStageSplitFromRunningApp(leftOrTop);
                    } catch (RemoteException e) {
                    } catch (RemoteException e) {
                        Log.w(TAG_OPS, "Unable to enter stage split from the current running app");
                        Log.w(TAG_OPS, "Unable to enter stage split from the current running app");
Loading