diff options
5 files changed, 97 insertions, 26 deletions
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java index 1239cdc5b606..45785238fe00 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java @@ -194,7 +194,8 @@ public abstract class WMShellModule { DisplayController displayController, SyncTransactionQueue syncQueue, Optional<DesktopModeController> desktopModeController, - Optional<DesktopTasksController> desktopTasksController) { + Optional<DesktopTasksController> desktopTasksController, + Optional<SplitScreenController> splitScreenController) { if (DesktopModeStatus.isAnyEnabled()) { return new DesktopModeWindowDecorViewModel( context, @@ -204,7 +205,8 @@ public abstract class WMShellModule { displayController, syncQueue, desktopModeController, - desktopTasksController); + desktopTasksController, + splitScreenController); } return new CaptionWindowDecorViewModel( context, diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java index c7ad4fdcacf0..94b9e907fa76 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java @@ -422,6 +422,11 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, mStageCoordinator.goToFullscreenFromSplit(); } + /** Move the specified task to fullscreen, regardless of focus state. */ + public void moveTaskToFullscreen(int taskId) { + mStageCoordinator.moveTaskToFullscreen(taskId); + } + public boolean isLaunchToSplit(TaskInfo taskInfo) { return mStageCoordinator.isLaunchToSplit(taskInfo); } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java index 2a6fbd2cee8c..a2ea9aacf958 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java @@ -2389,6 +2389,20 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, mSplitLayout.flingDividerToDismiss(!leftOrTop, EXIT_REASON_FULLSCREEN_SHORTCUT); } + /** Move the specified task to fullscreen, regardless of focus state. */ + public void moveTaskToFullscreen(int taskId) { + boolean leftOrTop; + if (mMainStage.containsTask(taskId)) { + leftOrTop = (mSideStagePosition == SPLIT_POSITION_TOP_OR_LEFT); + } else if (mSideStage.containsTask(taskId)) { + leftOrTop = (mSideStagePosition == SPLIT_POSITION_BOTTOM_OR_RIGHT); + } else { + return; + } + mSplitLayout.flingDividerToDismiss(!leftOrTop, EXIT_REASON_FULLSCREEN_SHORTCUT); + + } + boolean isLaunchToSplit(TaskInfo taskInfo) { return getActivateSplitPosition(taskInfo) != SPLIT_POSITION_UNDEFINED; } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java index de5f2f467e99..087e7a8a40fc 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java @@ -20,10 +20,14 @@ import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD; import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM; import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; +import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT; +import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT; + import android.app.ActivityManager; import android.app.ActivityManager.RunningTaskInfo; import android.app.ActivityTaskManager; import android.content.Context; +import android.graphics.Rect; import android.hardware.input.InputManager; import android.os.Handler; import android.os.Looper; @@ -37,7 +41,6 @@ import android.view.MotionEvent; import android.view.SurfaceControl; import android.view.View; import android.window.WindowContainerToken; -import android.window.WindowContainerTransaction; import androidx.annotation.Nullable; @@ -50,6 +53,7 @@ import com.android.wm.shell.desktopmode.DesktopModeController; import com.android.wm.shell.desktopmode.DesktopModeStatus; import com.android.wm.shell.desktopmode.DesktopTasksController; import com.android.wm.shell.freeform.FreeformTaskTransitionStarter; +import com.android.wm.shell.splitscreen.SplitScreenController; import java.util.Optional; @@ -80,6 +84,8 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel { private final InputMonitorFactory mInputMonitorFactory; private TaskOperations mTaskOperations; + private Optional<SplitScreenController> mSplitScreenController; + public DesktopModeWindowDecorViewModel( Context context, Handler mainHandler, @@ -88,7 +94,8 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel { DisplayController displayController, SyncTransactionQueue syncQueue, Optional<DesktopModeController> desktopModeController, - Optional<DesktopTasksController> desktopTasksController) { + Optional<DesktopTasksController> desktopTasksController, + Optional<SplitScreenController> splitScreenController) { this( context, mainHandler, @@ -98,6 +105,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel { syncQueue, desktopModeController, desktopTasksController, + splitScreenController, new DesktopModeWindowDecoration.Factory(), new InputMonitorFactory()); } @@ -112,6 +120,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel { SyncTransactionQueue syncQueue, Optional<DesktopModeController> desktopModeController, Optional<DesktopTasksController> desktopTasksController, + Optional<SplitScreenController> splitScreenController, DesktopModeWindowDecoration.Factory desktopModeWindowDecorFactory, InputMonitorFactory inputMonitorFactory) { mContext = context; @@ -120,6 +129,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel { mActivityTaskManager = mContext.getSystemService(ActivityTaskManager.class); mTaskOrganizer = taskOrganizer; mDisplayController = displayController; + mSplitScreenController = splitScreenController; mSyncQueue = syncQueue; mDesktopModeController = desktopModeController; mDesktopTasksController = desktopTasksController; @@ -230,6 +240,15 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel { final int id = v.getId(); if (id == R.id.close_window || id == R.id.close_button) { mTaskOperations.closeTask(mTaskToken); + if (mSplitScreenController.isPresent() + && mSplitScreenController.get().isSplitScreenVisible()) { + int remainingTaskPosition = mTaskId == mSplitScreenController.get() + .getTaskInfo(SPLIT_POSITION_TOP_OR_LEFT).taskId + ? SPLIT_POSITION_BOTTOM_OR_RIGHT : SPLIT_POSITION_TOP_OR_LEFT; + ActivityManager.RunningTaskInfo remainingTask = mSplitScreenController.get() + .getTaskInfo(remainingTaskPosition); + mSplitScreenController.get().moveTaskToFullscreen(remainingTask.taskId); + } } else if (id == R.id.back_button) { mTaskOperations.injectBackKey(); } else if (id == R.id.caption_handle) { @@ -261,9 +280,6 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel { if (taskInfo.isFocused) { return mDragDetector.isDragEvent(); } - final WindowContainerTransaction wct = new WindowContainerTransaction(); - wct.reorder(mTaskToken, true /* onTop */); - mSyncQueue.queue(wct); return false; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: @@ -401,14 +417,14 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel { * @param ev the {@link MotionEvent} received by {@link EventReceiver} */ private void handleReceivedMotionEvent(MotionEvent ev, InputMonitor inputMonitor) { + final DesktopModeWindowDecoration relevantDecor = getRelevantWindowDecor(ev); if (DesktopModeStatus.isProto2Enabled()) { - final DesktopModeWindowDecoration focusedDecor = getFocusedDecor(); - if (focusedDecor == null - || focusedDecor.mTaskInfo.getWindowingMode() != WINDOWING_MODE_FREEFORM) { - handleCaptionThroughStatusBar(ev); + if (relevantDecor == null + || relevantDecor.mTaskInfo.getWindowingMode() != WINDOWING_MODE_FREEFORM) { + handleCaptionThroughStatusBar(ev, relevantDecor); } } - handleEventOutsideFocusedCaption(ev); + handleEventOutsideFocusedCaption(ev, relevantDecor); // Prevent status bar from reacting to a caption drag. if (DesktopModeStatus.isProto2Enabled()) { if (mTransitionDragActive) { @@ -422,16 +438,16 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel { } // If an UP/CANCEL action is received outside of caption bounds, turn off handle menu - private void handleEventOutsideFocusedCaption(MotionEvent ev) { + private void handleEventOutsideFocusedCaption(MotionEvent ev, + DesktopModeWindowDecoration relevantDecor) { final int action = ev.getActionMasked(); if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) { - final DesktopModeWindowDecoration focusedDecor = getFocusedDecor(); - if (focusedDecor == null) { + if (relevantDecor == null) { return; } if (!mTransitionDragActive) { - focusedDecor.closeHandleMenuIfNeeded(ev); + relevantDecor.closeHandleMenuIfNeeded(ev); } } } @@ -441,39 +457,38 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel { * Perform caption actions if not able to through normal means. * Turn on desktop mode if handle is dragged below status bar. */ - private void handleCaptionThroughStatusBar(MotionEvent ev) { + private void handleCaptionThroughStatusBar(MotionEvent ev, + DesktopModeWindowDecoration relevantDecor) { switch (ev.getActionMasked()) { case MotionEvent.ACTION_DOWN: { // Begin drag through status bar if applicable. - final DesktopModeWindowDecoration focusedDecor = getFocusedDecor(); - if (focusedDecor != null) { + if (relevantDecor != null) { boolean dragFromStatusBarAllowed = false; if (DesktopModeStatus.isProto2Enabled()) { // In proto2 any full screen task can be dragged to freeform - dragFromStatusBarAllowed = focusedDecor.mTaskInfo.getWindowingMode() + dragFromStatusBarAllowed = relevantDecor.mTaskInfo.getWindowingMode() == WINDOWING_MODE_FULLSCREEN; } - if (dragFromStatusBarAllowed && focusedDecor.checkTouchEventInHandle(ev)) { + if (dragFromStatusBarAllowed && relevantDecor.checkTouchEventInHandle(ev)) { mTransitionDragActive = true; } } break; } case MotionEvent.ACTION_UP: { - final DesktopModeWindowDecoration focusedDecor = getFocusedDecor(); - if (focusedDecor == null) { + if (relevantDecor == null) { mTransitionDragActive = false; return; } if (mTransitionDragActive) { mTransitionDragActive = false; final int statusBarHeight = mDisplayController - .getDisplayLayout(focusedDecor.mTaskInfo.displayId).stableInsets().top; + .getDisplayLayout(relevantDecor.mTaskInfo.displayId).stableInsets().top; if (ev.getY() > statusBarHeight) { if (DesktopModeStatus.isProto2Enabled()) { mDesktopTasksController.ifPresent( - c -> c.moveToDesktop(focusedDecor.mTaskInfo)); + c -> c.moveToDesktop(relevantDecor.mTaskInfo)); } else if (DesktopModeStatus.isProto1Enabled()) { mDesktopModeController.ifPresent(c -> c.setDesktopModeActive(true)); } @@ -481,7 +496,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel { return; } } - focusedDecor.checkClickEvent(ev); + relevantDecor.checkClickEvent(ev); break; } case MotionEvent.ACTION_CANCEL: { @@ -491,6 +506,38 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel { } @Nullable + private DesktopModeWindowDecoration getRelevantWindowDecor(MotionEvent ev) { + if (mSplitScreenController.isPresent() + && mSplitScreenController.get().isSplitScreenVisible()) { + // We can't look at focused task here as only one task will have focus. + return getSplitScreenDecor(ev); + } else { + return getFocusedDecor(); + } + } + + @Nullable + private DesktopModeWindowDecoration getSplitScreenDecor(MotionEvent ev) { + ActivityManager.RunningTaskInfo topOrLeftTask = + mSplitScreenController.get().getTaskInfo(SPLIT_POSITION_TOP_OR_LEFT); + ActivityManager.RunningTaskInfo bottomOrRightTask = + mSplitScreenController.get().getTaskInfo(SPLIT_POSITION_BOTTOM_OR_RIGHT); + if (topOrLeftTask != null && topOrLeftTask.getConfiguration() + .windowConfiguration.getBounds().contains((int) ev.getX(), (int) ev.getY())) { + return mWindowDecorByTaskId.get(topOrLeftTask.taskId); + } else if (bottomOrRightTask != null && bottomOrRightTask.getConfiguration() + .windowConfiguration.getBounds().contains((int) ev.getX(), (int) ev.getY())) { + Rect bottomOrRightBounds = bottomOrRightTask.getConfiguration().windowConfiguration + .getBounds(); + ev.offsetLocation(-bottomOrRightBounds.left, -bottomOrRightBounds.top); + return mWindowDecorByTaskId.get(bottomOrRightTask.taskId); + } else { + return null; + } + + } + + @Nullable private DesktopModeWindowDecoration getFocusedDecor() { final int size = mWindowDecorByTaskId.size(); DesktopModeWindowDecoration focusedDecor = null; diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.java index 355072116cb1..1d1aa795173c 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.java @@ -49,6 +49,7 @@ import com.android.wm.shell.common.DisplayController; import com.android.wm.shell.common.SyncTransactionQueue; import com.android.wm.shell.desktopmode.DesktopModeController; import com.android.wm.shell.desktopmode.DesktopTasksController; +import com.android.wm.shell.splitscreen.SplitScreenController; import org.junit.Before; import org.junit.Test; @@ -73,6 +74,7 @@ public class DesktopModeWindowDecorViewModelTests extends ShellTestCase { @Mock private Choreographer mMainChoreographer; @Mock private ShellTaskOrganizer mTaskOrganizer; @Mock private DisplayController mDisplayController; + @Mock private SplitScreenController mSplitScreenController; @Mock private SyncTransactionQueue mSyncQueue; @Mock private DesktopModeController mDesktopModeController; @Mock private DesktopTasksController mDesktopTasksController; @@ -98,6 +100,7 @@ public class DesktopModeWindowDecorViewModelTests extends ShellTestCase { mSyncQueue, Optional.of(mDesktopModeController), Optional.of(mDesktopTasksController), + Optional.of(mSplitScreenController), mDesktopModeWindowDecorFactory, mMockInputMonitorFactory ); |