diff options
10 files changed, 281 insertions, 54 deletions
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeVisualIndicator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeVisualIndicator.java index 99f052832a51..56de48daf810 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeVisualIndicator.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeVisualIndicator.java @@ -49,6 +49,7 @@ import com.android.wm.shell.shared.annotations.ShellMainThread; import com.android.wm.shell.shared.bubbles.BubbleAnythingFlagHelper; import com.android.wm.shell.shared.bubbles.BubbleDropTargetBoundsProvider; import com.android.wm.shell.shared.desktopmode.DesktopModeStatus; +import com.android.wm.shell.windowdecor.tiling.SnapEventHandler; /** * Animated visual indicator for Desktop Mode windowing transitions. @@ -98,7 +99,9 @@ public class DesktopModeVisualIndicator { return FROM_SPLIT; } else if (taskInfo.isFreeform()) { return FROM_FREEFORM; - } else return null; + } else { + return null; + } } } @@ -110,6 +113,7 @@ public class DesktopModeVisualIndicator { private IndicatorType mCurrentType; private final DragStartState mDragStartState; + private final SnapEventHandler mSnapEventHandler; public DesktopModeVisualIndicator(@ShellDesktopThread ShellExecutor desktopExecutor, @ShellMainThread ShellExecutor mainExecutor, @@ -118,18 +122,20 @@ public class DesktopModeVisualIndicator { Context context, SurfaceControl taskSurface, RootTaskDisplayAreaOrganizer taskDisplayAreaOrganizer, DragStartState dragStartState, - @Nullable BubbleDropTargetBoundsProvider bubbleBoundsProvider) { + @Nullable BubbleDropTargetBoundsProvider bubbleBoundsProvider, + SnapEventHandler snapEventHandler) { SurfaceControl.Builder builder = new SurfaceControl.Builder(); taskDisplayAreaOrganizer.attachToDisplayArea(taskInfo.displayId, builder); mVisualIndicatorViewContainer = new VisualIndicatorViewContainer( DesktopModeFlags.ENABLE_DESKTOP_INDICATOR_IN_SEPARATE_THREAD_BUGFIX.isTrue() ? desktopExecutor : mainExecutor, - mainExecutor, builder, syncQueue, bubbleBoundsProvider); + mainExecutor, builder, syncQueue, bubbleBoundsProvider, snapEventHandler); mTaskInfo = taskInfo; mDisplayController = displayController; mContext = context; mCurrentType = NO_INDICATOR; mDragStartState = dragStartState; + mSnapEventHandler = snapEventHandler; mVisualIndicatorViewContainer.createView( mContext, mDisplayController.getDisplay(mTaskInfo.displayId), @@ -143,7 +149,8 @@ public class DesktopModeVisualIndicator { public void fadeOutIndicator( @NonNull Runnable callback) { mVisualIndicatorViewContainer.fadeOutIndicator( - mDisplayController.getDisplayLayout(mTaskInfo.displayId), mCurrentType, callback + mDisplayController.getDisplayLayout(mTaskInfo.displayId), mCurrentType, callback, + mTaskInfo.displayId, mSnapEventHandler ); } 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 1c880569fe7f..2d9aea014fbe 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 @@ -3051,6 +3051,7 @@ class DesktopTasksController( rootTaskDisplayAreaOrganizer, dragStartState, bubbleController.getOrNull()?.bubbleDropTargetBoundsProvider, + snapEventHandler, ) if (visualIndicator == null) visualIndicator = indicator return indicator.updateIndicatorType(PointF(inputX, taskTop)) diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/VisualIndicatorViewContainer.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/VisualIndicatorViewContainer.kt index 2317274dbbf0..919e8164b58e 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/VisualIndicatorViewContainer.kt +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/VisualIndicatorViewContainer.kt @@ -44,6 +44,7 @@ import com.android.wm.shell.shared.annotations.ShellDesktopThread import com.android.wm.shell.shared.annotations.ShellMainThread import com.android.wm.shell.shared.bubbles.BubbleDropTargetBoundsProvider import com.android.wm.shell.windowdecor.WindowDecoration.SurfaceControlViewHostFactory +import com.android.wm.shell.windowdecor.tiling.SnapEventHandler /** * Container for the view / viewhost of the indicator, ensuring it is created / animated off the @@ -60,6 +61,7 @@ constructor( private val surfaceControlViewHostFactory: SurfaceControlViewHostFactory = object : SurfaceControlViewHostFactory {}, private val bubbleBoundsProvider: BubbleDropTargetBoundsProvider?, + private val snapEventHandler: SnapEventHandler, ) { @VisibleForTesting var indicatorView: View? = null private var indicatorViewHost: SurfaceControlViewHost? = null @@ -164,9 +166,15 @@ constructor( displayController.getDisplayLayout(taskInfo.displayId) ?: error("Expected to find DisplayLayout for taskId${taskInfo.taskId}.") if (currentType == IndicatorType.NO_INDICATOR) { - fadeInIndicator(layout, newType) + fadeInIndicator(layout, newType, taskInfo.displayId, snapEventHandler) } else if (newType == IndicatorType.NO_INDICATOR) { - fadeOutIndicator(layout, currentType, /* finishCallback= */ null) + fadeOutIndicator( + layout, + currentType, + /* finishCallback= */ null, + taskInfo.displayId, + snapEventHandler, + ) } else { val animStartType = IndicatorType.valueOf(currentType.name) val animator = @@ -177,6 +185,8 @@ constructor( animStartType, newType, bubbleBoundsProvider, + taskInfo.displayId, + snapEventHandler, ) } ?: return@execute animator.start() @@ -188,12 +198,24 @@ constructor( * Fade indicator in as provided type. Animator fades it in while expanding the bounds outwards. */ @VisibleForTesting - fun fadeInIndicator(layout: DisplayLayout, type: IndicatorType) { + fun fadeInIndicator( + layout: DisplayLayout, + type: IndicatorType, + displayId: Int, + snapEventHandler: SnapEventHandler, + ) { desktopExecutor.assertCurrentThread() indicatorView?.let { it.setBackgroundResource(R.drawable.desktop_windowing_transition_background) val animator = - VisualIndicatorAnimator.fadeBoundsIn(it, type, layout, bubbleBoundsProvider) + VisualIndicatorAnimator.fadeBoundsIn( + it, + type, + layout, + bubbleBoundsProvider, + displayId, + snapEventHandler, + ) animator.start() } } @@ -207,6 +229,8 @@ constructor( layout: DisplayLayout, currentType: IndicatorType, finishCallback: Runnable?, + displayId: Int, + snapEventHandler: SnapEventHandler, ) { if (currentType == IndicatorType.NO_INDICATOR) { // In rare cases, fade out can be requested before the indicator has determined its @@ -223,6 +247,8 @@ constructor( animStartType, layout, bubbleBoundsProvider, + displayId, + snapEventHandler, ) animator.addListener( object : AnimatorListenerAdapter() { @@ -328,8 +354,17 @@ constructor( type: IndicatorType, displayLayout: DisplayLayout, bubbleBoundsProvider: BubbleDropTargetBoundsProvider?, + displayId: Int, + snapEventHandler: SnapEventHandler, ): VisualIndicatorAnimator { - val endBounds = getIndicatorBounds(displayLayout, type, bubbleBoundsProvider) + val endBounds = + getIndicatorBounds( + displayLayout, + type, + bubbleBoundsProvider, + displayId, + snapEventHandler, + ) val startBounds = getMinBounds(endBounds) view.background.bounds = startBounds @@ -345,11 +380,19 @@ constructor( type: IndicatorType, displayLayout: DisplayLayout, bubbleBoundsProvider: BubbleDropTargetBoundsProvider?, + displayId: Int, + snapEventHandler: SnapEventHandler, ): VisualIndicatorAnimator { - val startBounds = getIndicatorBounds(displayLayout, type, bubbleBoundsProvider) + val startBounds = + getIndicatorBounds( + displayLayout, + type, + bubbleBoundsProvider, + displayId, + snapEventHandler, + ) val endBounds = getMinBounds(startBounds) view.background.bounds = startBounds - val animator = VisualIndicatorAnimator(view, startBounds, endBounds) animator.interpolator = DecelerateInterpolator() setupIndicatorAnimation(animator, AlphaAnimType.ALPHA_FADE_OUT_ANIM) @@ -375,9 +418,25 @@ constructor( origType: IndicatorType, newType: IndicatorType, bubbleBoundsProvider: BubbleDropTargetBoundsProvider?, + displayId: Int, + snapEventHandler: SnapEventHandler, ): VisualIndicatorAnimator { - val startBounds = getIndicatorBounds(displayLayout, origType, bubbleBoundsProvider) - val endBounds = getIndicatorBounds(displayLayout, newType, bubbleBoundsProvider) + val startBounds = + getIndicatorBounds( + displayLayout, + origType, + bubbleBoundsProvider, + displayId, + snapEventHandler, + ) + val endBounds = + getIndicatorBounds( + displayLayout, + newType, + bubbleBoundsProvider, + displayId, + snapEventHandler, + ) val animator = VisualIndicatorAnimator(view, startBounds, endBounds) animator.interpolator = DecelerateInterpolator() setupIndicatorAnimation(animator, AlphaAnimType.ALPHA_NO_CHANGE_ANIM) @@ -389,6 +448,8 @@ constructor( layout: DisplayLayout, type: IndicatorType, bubbleBoundsProvider: BubbleDropTargetBoundsProvider?, + displayId: Int, + snapEventHandler: SnapEventHandler, ): Rect { val desktopStableBounds = Rect() layout.getStableBounds(desktopStableBounds) @@ -417,21 +478,25 @@ constructor( ) } - IndicatorType.TO_SPLIT_LEFT_INDICATOR -> + IndicatorType.TO_SPLIT_LEFT_INDICATOR -> { + val currentLeftBounds = snapEventHandler.getLeftSnapBoundsIfTiled(displayId) return Rect( padding, padding, - desktopStableBounds.width() / 2 - padding, + currentLeftBounds.right - padding, desktopStableBounds.height(), ) - - IndicatorType.TO_SPLIT_RIGHT_INDICATOR -> + } + IndicatorType.TO_SPLIT_RIGHT_INDICATOR -> { + val currentRightBounds = + snapEventHandler.getRightSnapBoundsIfTiled(displayId) return Rect( - desktopStableBounds.width() / 2 + padding, + currentRightBounds.left + padding, padding, desktopStableBounds.width() - padding, desktopStableBounds.height(), ) + } IndicatorType.TO_BUBBLE_LEFT_INDICATOR -> return bubbleBoundsProvider?.getBubbleBarExpandedViewDropTargetBounds( /* onLeft= */ true 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 d9afd1503db5..0d773ecf88e4 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 @@ -159,6 +159,8 @@ import kotlin.Pair; import kotlin.Unit; import kotlin.jvm.functions.Function1; +import org.jetbrains.annotations.NotNull; + import kotlinx.coroutines.CoroutineScope; import kotlinx.coroutines.ExperimentalCoroutinesApi; import kotlinx.coroutines.MainCoroutineDispatcher; @@ -935,6 +937,18 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel, return mDesktopTilingDecorViewModel.moveTaskToFrontIfTiled(taskInfo); } + @Override + @NotNull + public Rect getLeftSnapBoundsIfTiled(int displayId) { + return mDesktopTilingDecorViewModel.getLeftSnapBoundsIfTiled(displayId); + } + + @Override + @NotNull + public Rect getRightSnapBoundsIfTiled(int displayId) { + return mDesktopTilingDecorViewModel.getRightSnapBoundsIfTiled(displayId); + } + private class DesktopModeTouchEventListener extends GestureDetector.SimpleOnGestureListener implements View.OnClickListener, View.OnTouchListener, View.OnLongClickListener, View.OnGenericMotionListener, DragDetector.MotionEventHandler { @@ -974,7 +988,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel, final int touchSlop = ViewConfiguration.get(mContext).getScaledTouchSlop(); final long appHandleHoldToDragDuration = DesktopModeFlags.ENABLE_HOLD_TO_DRAG_APP_HANDLE.isTrue() - ? APP_HANDLE_HOLD_TO_DRAG_DURATION_MS : 0; + ? APP_HANDLE_HOLD_TO_DRAG_DURATION_MS : 0; mHandleDragDetector = new DragDetector(this, appHandleHoldToDragDuration, touchSlop); mHeaderDragDetector = new DragDetector(this, APP_HEADER_HOLD_TO_DRAG_DURATION_MS, @@ -1027,7 +1041,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel, decoration.mTaskInfo.userId); if (DesktopModeFlags.ENABLE_FULLY_IMMERSIVE_IN_DESKTOP.isTrue() && desktopRepository.isTaskInFullImmersiveState( - decoration.mTaskInfo.taskId)) { + decoration.mTaskInfo.taskId)) { // Task is in immersive and should exit. onEnterOrExitImmersive(decoration.mTaskInfo); } else { @@ -1321,6 +1335,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel, /** * Perform a task size toggle on release of the double-tap, assuming no drag event * was handled during the double-tap. + * * @param e The motion event that occurred during the double-tap gesture. * @return true if the event should be consumed, false if not */ @@ -1346,6 +1361,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel, class EventReceiver extends InputEventReceiver { private InputMonitor mInputMonitor; private int mTasksOnDisplay; + EventReceiver(InputMonitor inputMonitor, InputChannel channel, Looper looper) { super(channel, looper); mInputMonitor = inputMonitor; @@ -1397,6 +1413,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel, /** * Check if an EventReceiver exists on a particular display. * If it does, increment its task count. Otherwise, create one for that display. + * * @param displayId the display to check against */ private void incrementEventReceiverTasks(int displayId) { @@ -1902,7 +1919,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel, @Override public void onAnimationStart(int taskId, Transaction t, Rect bounds) { final DesktopModeWindowDecoration decoration = mWindowDecorByTaskId.get(taskId); - if (decoration == null) { + if (decoration == null) { t.apply(); return; } @@ -1986,15 +2003,15 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel, return activityTaskManager.getRecentTasks(Integer.MAX_VALUE, ActivityManager.RECENT_WITH_EXCLUDED, info.userId).getList().stream().filter( - recentTaskInfo -> { - if (recentTaskInfo.taskId == info.taskId) { - return false; - } - final String recentTaskPackageName = - ComponentUtils.getPackageName(recentTaskInfo); - return packageName != null - && packageName.equals(recentTaskPackageName); - } + recentTaskInfo -> { + if (recentTaskInfo.taskId == info.taskId) { + return false; + } + final String recentTaskPackageName = + ComponentUtils.getPackageName(recentTaskInfo); + return packageName != null + && packageName.equals(recentTaskPackageName); + } ).toList().size(); } catch (RemoteException e) { throw new RuntimeException(e); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/tiling/DesktopTilingDecorViewModel.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/tiling/DesktopTilingDecorViewModel.kt index 8747f63e789f..ee5d0e80d90c 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/tiling/DesktopTilingDecorViewModel.kt +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/tiling/DesktopTilingDecorViewModel.kt @@ -25,6 +25,7 @@ import android.window.DisplayAreaInfo import android.window.WindowContainerTransaction import androidx.core.util.valueIterator import com.android.internal.annotations.VisibleForTesting +import com.android.wm.shell.R import com.android.wm.shell.RootTaskDisplayAreaOrganizer import com.android.wm.shell.ShellTaskOrganizer import com.android.wm.shell.common.DisplayChangeController @@ -148,4 +149,45 @@ class DesktopTilingDecorViewModel( if ((fromRotation % 2 == toRotation % 2)) return tilingTransitionHandlerByDisplayId.get(displayId)?.resetTilingSession() } + + fun getRightSnapBoundsIfTiled(displayId: Int): Rect { + val tilingBounds = + tilingTransitionHandlerByDisplayId.get(displayId)?.getRightSnapBoundsIfTiled() + if (tilingBounds != null) { + return tilingBounds + } + val displayLayout = displayController.getDisplayLayout(displayId) + val stableBounds = Rect() + displayLayout?.getStableBounds(stableBounds) + val snapBounds = + Rect( + stableBounds.left + + stableBounds.width() / 2 + + context.resources.getDimensionPixelSize(R.dimen.split_divider_bar_width) / 2, + stableBounds.top, + stableBounds.right, + stableBounds.bottom, + ) + return snapBounds + } + + fun getLeftSnapBoundsIfTiled(displayId: Int): Rect { + val tilingBounds = + tilingTransitionHandlerByDisplayId.get(displayId)?.getLeftSnapBoundsIfTiled() + if (tilingBounds != null) { + return tilingBounds + } + val displayLayout = displayController.getDisplayLayout(displayId) + val stableBounds = Rect() + displayLayout?.getStableBounds(stableBounds) + val snapBounds = + Rect( + stableBounds.left, + stableBounds.top, + stableBounds.left + stableBounds.width() / 2 - + context.resources.getDimensionPixelSize(R.dimen.split_divider_bar_width) / 2, + stableBounds.bottom, + ) + return snapBounds + } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/tiling/DesktopTilingWindowDecoration.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/tiling/DesktopTilingWindowDecoration.kt index 666d4bd046dc..983332565bd9 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/tiling/DesktopTilingWindowDecoration.kt +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/tiling/DesktopTilingWindowDecoration.kt @@ -36,7 +36,6 @@ import android.window.WindowContainerTransaction import com.android.internal.annotations.VisibleForTesting import com.android.launcher3.icons.BaseIconFactory import com.android.window.flags.Flags -import com.android.wm.shell.shared.FocusTransitionListener import com.android.wm.shell.R import com.android.wm.shell.RootTaskDisplayAreaOrganizer import com.android.wm.shell.ShellTaskOrganizer @@ -50,6 +49,7 @@ import com.android.wm.shell.desktopmode.DesktopTasksController.SnapPosition import com.android.wm.shell.desktopmode.DesktopUserRepositories import com.android.wm.shell.desktopmode.ReturnToDragStartAnimator import com.android.wm.shell.desktopmode.ToggleResizeDesktopTaskTransitionHandler +import com.android.wm.shell.shared.FocusTransitionListener import com.android.wm.shell.shared.annotations.ShellBackgroundThread import com.android.wm.shell.shared.annotations.ShellMainThread import com.android.wm.shell.transition.FocusTransitionObserver @@ -112,7 +112,7 @@ class DesktopTilingWindowDecoration( position: SnapPosition, currentBounds: Rect, ): Boolean { - val destinationBounds = getSnapBounds(taskInfo, position) + val destinationBounds = getSnapBounds(position) val resizeMetadata = AppResizingHelper( taskInfo, @@ -502,9 +502,11 @@ class DesktopTilingWindowDecoration( } // Overriding FocusTransitionListener - override fun onFocusedTaskChanged(taskId: Int, - isFocusedOnDisplay: Boolean, - isFocusedGlobally: Boolean) { + override fun onFocusedTaskChanged( + taskId: Int, + isFocusedOnDisplay: Boolean, + isFocusedGlobally: Boolean, + ) { if (!Flags.enableDisplayFocusInShellTransitions()) return moveTiledPairToFront(taskId, isFocusedOnDisplay) } @@ -512,7 +514,7 @@ class DesktopTilingWindowDecoration( // Only called if [taskInfo] relates to a focused task private fun isTilingRefocused(taskId: Int): Boolean { return taskId == leftTaskResizingHelper?.taskInfo?.taskId || - taskId == rightTaskResizingHelper?.taskInfo?.taskId + taskId == rightTaskResizingHelper?.taskInfo?.taskId } private fun buildTiledTasksMoveToFront(leftOnTop: Boolean): WindowContainerTransaction { @@ -623,26 +625,24 @@ class DesktopTilingWindowDecoration( val t = transactionSupplier.get() if (!Flags.enableDisplayFocusInShellTransitions()) isTilingFocused = true if (taskId == leftTaskResizingHelper?.taskInfo?.taskId) { - desktopTilingDividerWindowManager?.onRelativeLeashChanged( - leftTiledTask.getLeash(), - t, - ) + desktopTilingDividerWindowManager?.onRelativeLeashChanged(leftTiledTask.getLeash(), t) } if (taskId == rightTaskResizingHelper?.taskInfo?.taskId) { - desktopTilingDividerWindowManager?.onRelativeLeashChanged( - rightTiledTask.getLeash(), - t, - ) + desktopTilingDividerWindowManager?.onRelativeLeashChanged(rightTiledTask.getLeash(), t) } - transitions.startTransition( - TRANSIT_TO_FRONT, - buildTiledTasksMoveToFront(isLeftOnTop), - null, - ) + transitions.startTransition(TRANSIT_TO_FRONT, buildTiledTasksMoveToFront(isLeftOnTop), null) t.apply() return true } + fun getRightSnapBoundsIfTiled(): Rect { + return getSnapBounds(SnapPosition.RIGHT) + } + + fun getLeftSnapBoundsIfTiled(): Rect { + return getSnapBounds(SnapPosition.LEFT) + } + private fun allTiledTasksVisible(): Boolean { val leftTiledTask = leftTaskResizingHelper ?: return false val rightTiledTask = rightTaskResizingHelper ?: return false @@ -674,8 +674,8 @@ class DesktopTilingWindowDecoration( ) } - private fun getSnapBounds(taskInfo: RunningTaskInfo, position: SnapPosition): Rect { - val displayLayout = displayController.getDisplayLayout(taskInfo.displayId) ?: return Rect() + private fun getSnapBounds(position: SnapPosition): Rect { + val displayLayout = displayController.getDisplayLayout(displayId) ?: return Rect() val stableBounds = Rect() displayLayout.getStableBounds(stableBounds) diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/tiling/SnapEventHandler.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/tiling/SnapEventHandler.kt index 52e24d6fe0d0..b9d674110eb2 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/tiling/SnapEventHandler.kt +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/tiling/SnapEventHandler.kt @@ -40,4 +40,16 @@ interface SnapEventHandler { /** If a task is tiled, delegate moving to front to tiling infrastructure. */ fun moveTaskToFrontIfTiled(taskInfo: RunningTaskInfo): Boolean + + /** + * Returns the bounds of a task tiled on the left on the specified display, defaults to default + * snapping bounds if no task is tiled. + */ + fun getLeftSnapBoundsIfTiled(displayId: Int): Rect + + /** + * Returns the bounds of a task tiled on the right on the specified display, defaults to default + * snapping bounds if no task is tiled. + */ + fun getRightSnapBoundsIfTiled(displayId: Int): Rect } diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeVisualIndicatorTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeVisualIndicatorTest.kt index 20d50aa32f7f..dcc9e2415039 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeVisualIndicatorTest.kt +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeVisualIndicatorTest.kt @@ -36,6 +36,7 @@ import com.android.wm.shell.common.DisplayController import com.android.wm.shell.common.DisplayLayout import com.android.wm.shell.common.SyncTransactionQueue import com.android.wm.shell.shared.bubbles.BubbleDropTargetBoundsProvider +import com.android.wm.shell.windowdecor.tiling.SnapEventHandler import com.google.common.truth.Truth.assertThat import org.junit.Before import org.junit.Rule @@ -67,6 +68,7 @@ class DesktopModeVisualIndicatorTest : ShellTestCase() { @Mock private lateinit var taskDisplayAreaOrganizer: RootTaskDisplayAreaOrganizer @Mock private lateinit var displayLayout: DisplayLayout @Mock private lateinit var bubbleBoundsProvider: BubbleDropTargetBoundsProvider + @Mock private lateinit var snapEventHandler: SnapEventHandler private lateinit var visualIndicator: DesktopModeVisualIndicator private val desktopExecutor = TestShellExecutor() @@ -356,6 +358,7 @@ class DesktopModeVisualIndicatorTest : ShellTestCase() { taskDisplayAreaOrganizer, dragStartState, bubbleBoundsProvider, + snapEventHandler, ) } diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/VisualIndicatorViewContainerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/VisualIndicatorViewContainerTest.kt index 79b0f1c7eadd..4c8cb3823f7e 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/VisualIndicatorViewContainerTest.kt +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/VisualIndicatorViewContainerTest.kt @@ -38,6 +38,7 @@ import com.android.wm.shell.common.DisplayLayout import com.android.wm.shell.common.SyncTransactionQueue import com.android.wm.shell.shared.bubbles.BubbleDropTargetBoundsProvider import com.android.wm.shell.windowdecor.WindowDecoration.SurfaceControlViewHostFactory +import com.android.wm.shell.windowdecor.tiling.SnapEventHandler import com.google.common.truth.Truth.assertThat import kotlin.test.Test import org.junit.Before @@ -71,6 +72,7 @@ class VisualIndicatorViewContainerTest : ShellTestCase() { @Mock private lateinit var mockSurfaceControlViewHostFactory: SurfaceControlViewHostFactory @Mock private lateinit var mockBackground: LayerDrawable @Mock private lateinit var bubbleDropTargetBoundsProvider: BubbleDropTargetBoundsProvider + @Mock private lateinit var snapEventHandler: SnapEventHandler private val taskInfo: RunningTaskInfo = createTaskInfo() private val mainExecutor = TestShellExecutor() private val desktopExecutor = TestShellExecutor() @@ -81,6 +83,8 @@ class VisualIndicatorViewContainerTest : ShellTestCase() { whenever(displayLayout.getStableBounds(any())).thenAnswer { i -> (i.arguments.first() as Rect).set(DISPLAY_BOUNDS) } + whenever(snapEventHandler.getRightSnapBoundsIfTiled(any())).thenReturn(Rect(1, 2, 3, 4)) + whenever(snapEventHandler.getLeftSnapBoundsIfTiled(any())).thenReturn(Rect(5, 6, 7, 8)) whenever(mockSurfaceControlViewHostFactory.create(any(), any(), any())) .thenReturn(mock(SurfaceControlViewHost::class.java)) } @@ -117,7 +121,7 @@ class VisualIndicatorViewContainerTest : ShellTestCase() { DesktopModeVisualIndicator.IndicatorType.TO_FULLSCREEN_INDICATOR, ) desktopExecutor.flushAll() - verify(spyViewContainer).fadeInIndicator(any(), any()) + verify(spyViewContainer).fadeInIndicator(any(), any(), any(), any()) } @Test @@ -135,6 +139,8 @@ class VisualIndicatorViewContainerTest : ShellTestCase() { any(), eq(DesktopModeVisualIndicator.IndicatorType.TO_FULLSCREEN_INDICATOR), anyOrNull(), + eq(taskInfo.displayId), + eq(snapEventHandler), ) } @@ -167,6 +173,8 @@ class VisualIndicatorViewContainerTest : ShellTestCase() { DesktopModeVisualIndicator.IndicatorType.TO_FULLSCREEN_INDICATOR, displayLayout, bubbleDropTargetBoundsProvider, + taskInfo.displayId, + snapEventHandler, ) } assertThat(animator?.indicatorStartBounds).isEqualTo(Rect(15, 15, 985, 985)) @@ -174,6 +182,46 @@ class VisualIndicatorViewContainerTest : ShellTestCase() { } @Test + fun testFadeInBoundsCalculationForLeftSnap() { + val spyIndicator = setupSpyViewContainer() + val animator = + spyIndicator.indicatorView?.let { + VisualIndicatorViewContainer.VisualIndicatorAnimator.fadeBoundsIn( + it, + DesktopModeVisualIndicator.IndicatorType.TO_SPLIT_LEFT_INDICATOR, + displayLayout, + bubbleDropTargetBoundsProvider, + taskInfo.displayId, + snapEventHandler, + ) + } + + // Right bound is the same as whatever right bound snapEventHandler returned minus padding, + // in this case, the right bound for the left app is 7. + assertThat(animator?.indicatorEndBounds).isEqualTo(Rect(0, 0, 7, 1000)) + } + + @Test + fun testFadeInBoundsCalculationForRightSnap() { + val spyIndicator = setupSpyViewContainer() + val animator = + spyIndicator.indicatorView?.let { + VisualIndicatorViewContainer.VisualIndicatorAnimator.fadeBoundsIn( + it, + DesktopModeVisualIndicator.IndicatorType.TO_SPLIT_RIGHT_INDICATOR, + displayLayout, + bubbleDropTargetBoundsProvider, + taskInfo.displayId, + snapEventHandler, + ) + } + + // Left bound is the same as whatever left bound snapEventHandler returned plus padding + // in this case, the left bound of the right app is 1. + assertThat(animator?.indicatorEndBounds).isEqualTo(Rect(1, 0, 1000, 1000)) + } + + @Test fun testFadeOutBoundsCalculation() { val spyIndicator = setupSpyViewContainer() val animator = @@ -183,6 +231,8 @@ class VisualIndicatorViewContainerTest : ShellTestCase() { DesktopModeVisualIndicator.IndicatorType.TO_FULLSCREEN_INDICATOR, displayLayout, bubbleDropTargetBoundsProvider, + taskInfo.displayId, + snapEventHandler, ) } assertThat(animator?.indicatorStartBounds).isEqualTo(Rect(0, 0, 1000, 1000)) @@ -199,6 +249,8 @@ class VisualIndicatorViewContainerTest : ShellTestCase() { DesktopModeVisualIndicator.IndicatorType.TO_FULLSCREEN_INDICATOR, DesktopModeVisualIndicator.IndicatorType.TO_SPLIT_LEFT_INDICATOR, bubbleDropTargetBoundsProvider, + taskInfo.displayId, + snapEventHandler, ) // Test desktop to split-right bounds. animator = @@ -208,6 +260,8 @@ class VisualIndicatorViewContainerTest : ShellTestCase() { DesktopModeVisualIndicator.IndicatorType.TO_DESKTOP_INDICATOR, DesktopModeVisualIndicator.IndicatorType.TO_SPLIT_RIGHT_INDICATOR, bubbleDropTargetBoundsProvider, + taskInfo.displayId, + snapEventHandler, ) } @@ -220,6 +274,7 @@ class VisualIndicatorViewContainerTest : ShellTestCase() { syncQueue, mockSurfaceControlViewHostFactory, bubbleDropTargetBoundsProvider, + snapEventHandler, ) viewContainer.createView( context, diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/tiling/DesktopTilingDecorViewModelTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/tiling/DesktopTilingDecorViewModelTest.kt index 2cabb9a33b86..646ec21cab9b 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/tiling/DesktopTilingDecorViewModelTest.kt +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/tiling/DesktopTilingDecorViewModelTest.kt @@ -16,6 +16,7 @@ package com.android.wm.shell.windowdecor.tiling import android.content.Context +import android.content.res.Resources import android.graphics.Rect import android.testing.AndroidTestingRunner import androidx.test.filters.SmallTest @@ -23,12 +24,13 @@ import com.android.wm.shell.RootTaskDisplayAreaOrganizer import com.android.wm.shell.ShellTaskOrganizer import com.android.wm.shell.ShellTestCase import com.android.wm.shell.common.DisplayController +import com.android.wm.shell.common.DisplayLayout import com.android.wm.shell.common.ShellExecutor import com.android.wm.shell.common.SyncTransactionQueue import com.android.wm.shell.desktopmode.DesktopModeEventLogger -import com.android.wm.shell.desktopmode.DesktopUserRepositories import com.android.wm.shell.desktopmode.DesktopTasksController import com.android.wm.shell.desktopmode.DesktopTestHelpers.createFreeformTask +import com.android.wm.shell.desktopmode.DesktopUserRepositories import com.android.wm.shell.desktopmode.ReturnToDragStartAnimator import com.android.wm.shell.desktopmode.ToggleResizeDesktopTaskTransitionHandler import com.android.wm.shell.transition.FocusTransitionObserver @@ -52,6 +54,7 @@ import org.mockito.kotlin.whenever @RunWith(AndroidTestingRunner::class) class DesktopTilingDecorViewModelTest : ShellTestCase() { private val contextMock: Context = mock() + private val resourcesMock: Resources = mock() private val mainDispatcher: MainCoroutineDispatcher = mock() private val bgScope: CoroutineScope = mock() private val displayControllerMock: DisplayController = mock() @@ -70,6 +73,7 @@ class DesktopTilingDecorViewModelTest : ShellTestCase() { private val desktopTilingDecoration: DesktopTilingWindowDecoration = mock() private val taskResourceLoader: WindowDecorTaskResourceLoader = mock() private val focusTransitionObserver: FocusTransitionObserver = mock() + private val displayLayout: DisplayLayout = mock() private val mainExecutor: ShellExecutor = mock() private lateinit var desktopTilingDecorViewModel: DesktopTilingDecorViewModel @@ -91,9 +95,16 @@ class DesktopTilingDecorViewModelTest : ShellTestCase() { desktopModeEventLogger, taskResourceLoader, focusTransitionObserver, - mainExecutor + mainExecutor, ) whenever(contextMock.createContextAsUser(any(), any())).thenReturn(contextMock) + whenever(displayControllerMock.getDisplayLayout(any())).thenReturn(displayLayout) + whenever(displayLayout.getStableBounds(any())).thenAnswer { i -> + (i.arguments.first() as Rect).set(STABLE_BOUNDS) + } + whenever(contextMock.createContextAsUser(any(), any())).thenReturn(context) + whenever(contextMock.resources).thenReturn(resourcesMock) + whenever(resourcesMock.getDimensionPixelSize(any())).thenReturn(10) } @Test @@ -202,7 +213,21 @@ class DesktopTilingDecorViewModelTest : ShellTestCase() { verify(desktopTilingDecoration, times(1)).resetTilingSession() } + @Test + fun getTiledAppBounds_NoTilingTransitionHandlerObject() { + // Right bound of the left app here represents default 8 / 2 - 2 ( {Right bound} / 2 - + // {divider pixel size}) + assertThat(desktopTilingDecorViewModel.getLeftSnapBoundsIfTiled(1)) + .isEqualTo(Rect(6, 7, 2, 9)) + + // Left bound of the right app here represents default 8 / 2 + 6 + 2 ( {Left bound} + + // {width}/ 2 + {divider pixel size}) + assertThat(desktopTilingDecorViewModel.getRightSnapBoundsIfTiled(1)) + .isEqualTo(Rect(12, 7, 8, 9)) + } + companion object { private val BOUNDS = Rect(1, 2, 3, 4) + private val STABLE_BOUNDS = Rect(6, 7, 8, 9) } } |