Loading libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java +4 −2 Original line number Diff line number Diff line Loading @@ -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, Loading @@ -204,7 +205,8 @@ public abstract class WMShellModule { displayController, syncQueue, desktopModeController, desktopTasksController); desktopTasksController, splitScreenController); } return new CaptionWindowDecorViewModel( context, Loading libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java +5 −0 Original line number Diff line number Diff line Loading @@ -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); } Loading libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java +14 −0 Original line number Diff line number Diff line Loading @@ -2390,6 +2390,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; } Loading libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java +71 −24 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading @@ -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; Loading Loading @@ -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, Loading @@ -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, Loading @@ -98,6 +105,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel { syncQueue, desktopModeController, desktopTasksController, splitScreenController, new DesktopModeWindowDecoration.Factory(), new InputMonitorFactory()); } Loading @@ -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; Loading @@ -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; Loading Loading @@ -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) { Loading Loading @@ -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: Loading Loading @@ -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) { Loading @@ -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); } } } Loading @@ -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)); } Loading @@ -481,7 +496,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel { return; } } focusedDecor.checkClickEvent(ev); relevantDecor.checkClickEvent(ev); break; } case MotionEvent.ACTION_CANCEL: { Loading @@ -490,6 +505,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(); Loading libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.java +3 −0 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading @@ -98,6 +100,7 @@ public class DesktopModeWindowDecorViewModelTests extends ShellTestCase { mSyncQueue, Optional.of(mDesktopModeController), Optional.of(mDesktopTasksController), Optional.of(mSplitScreenController), mDesktopModeWindowDecorFactory, mMockInputMonitorFactory ); Loading Loading
libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java +4 −2 Original line number Diff line number Diff line Loading @@ -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, Loading @@ -204,7 +205,8 @@ public abstract class WMShellModule { displayController, syncQueue, desktopModeController, desktopTasksController); desktopTasksController, splitScreenController); } return new CaptionWindowDecorViewModel( context, Loading
libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java +5 −0 Original line number Diff line number Diff line Loading @@ -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); } Loading
libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java +14 −0 Original line number Diff line number Diff line Loading @@ -2390,6 +2390,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; } Loading
libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java +71 −24 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading @@ -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; Loading Loading @@ -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, Loading @@ -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, Loading @@ -98,6 +105,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel { syncQueue, desktopModeController, desktopTasksController, splitScreenController, new DesktopModeWindowDecoration.Factory(), new InputMonitorFactory()); } Loading @@ -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; Loading @@ -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; Loading Loading @@ -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) { Loading Loading @@ -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: Loading Loading @@ -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) { Loading @@ -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); } } } Loading @@ -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)); } Loading @@ -481,7 +496,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel { return; } } focusedDecor.checkClickEvent(ev); relevantDecor.checkClickEvent(ev); break; } case MotionEvent.ACTION_CANCEL: { Loading @@ -490,6 +505,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(); Loading
libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.java +3 −0 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading @@ -98,6 +100,7 @@ public class DesktopModeWindowDecorViewModelTests extends ShellTestCase { mSyncQueue, Optional.of(mDesktopModeController), Optional.of(mDesktopTasksController), Optional.of(mSplitScreenController), mDesktopModeWindowDecorFactory, mMockInputMonitorFactory ); Loading