Loading core/java/com/android/internal/policy/DesktopModeCompatUtils.java +27 −0 Original line number Diff line number Diff line Loading @@ -25,6 +25,7 @@ import android.annotation.NonNull; import android.content.pm.ActivityInfo; import android.content.res.Configuration; import android.graphics.Rect; import android.view.Gravity; import android.window.DesktopModeFlags; /** Loading Loading @@ -52,6 +53,32 @@ public final class DesktopModeCompatUtils { || info.isChangeEnabled(OVERRIDE_EXCLUDE_CAPTION_INSETS_FROM_APP_BOUNDS)); } /** * Applies a vertical and horizontal gravity on the inOutBounds in relation to the stableBounds. */ public static void applyLayoutGravity(int verticalGravity, int horizontalGravity, @NonNull Rect inOutBounds, @NonNull Rect stableBounds) { final int width = inOutBounds.width(); final int height = inOutBounds.height(); final float fractionOfHorizontalOffset = switch (horizontalGravity) { case Gravity.LEFT -> 0f; case Gravity.RIGHT -> 1f; default -> 0.5f; }; final float fractionOfVerticalOffset = switch (verticalGravity) { case Gravity.TOP -> 0f; case Gravity.BOTTOM -> 1f; default -> 0.5f; }; inOutBounds.offsetTo(stableBounds.left, stableBounds.top); final int xOffset = (int) (fractionOfHorizontalOffset * (stableBounds.width() - width)); final int yOffset = (int) (fractionOfVerticalOffset * (stableBounds.height() - height)); inOutBounds.offset(xOffset, yOffset); } /** * Returns the orientation of the given {@code rect}. */ Loading libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTaskPosition.kt +11 −9 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ import android.graphics.Point import android.graphics.Rect import android.view.Gravity import com.android.internal.annotations.VisibleForTesting import com.android.internal.policy.DesktopModeCompatUtils.applyLayoutGravity import com.android.wm.shell.R import com.android.wm.shell.desktopmode.DesktopTaskPosition.BottomLeft import com.android.wm.shell.desktopmode.DesktopTaskPosition.BottomRight Loading Loading @@ -81,18 +82,19 @@ sealed class DesktopTaskPosition { abstract fun next(): DesktopTaskPosition } /** * If the app has specified horizontal or vertical gravity layout, don't change the task position * for cascading effect. */ fun canChangeTaskPosition(taskInfo: TaskInfo): Boolean { fun applyLayoutGravityIfNeeded(taskInfo: TaskInfo, bounds: Rect, stableBounds: Rect): Boolean { var horizontalGravity = 0 var verticalGravity = 0 taskInfo.topActivityInfo?.windowLayout?.let { val horizontalGravityApplied = it.gravity.and(Gravity.HORIZONTAL_GRAVITY_MASK) val verticalGravityApplied = it.gravity.and(Gravity.VERTICAL_GRAVITY_MASK) return horizontalGravityApplied == 0 && verticalGravityApplied == 0 horizontalGravity = it.gravity.and(Gravity.HORIZONTAL_GRAVITY_MASK) verticalGravity = it.gravity.and(Gravity.VERTICAL_GRAVITY_MASK) } if (verticalGravity > 0 || horizontalGravity > 0) { applyLayoutGravity(verticalGravity, horizontalGravity, bounds, stableBounds) return true } return false } /** Returns the current DesktopTaskPosition for a given window in the frame. */ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) Loading libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt +9 −5 Original line number Diff line number Diff line Loading @@ -4438,10 +4438,8 @@ class DesktopTasksController( wct.setBounds(task.token, inheritedTaskBounds) } else { val initialBounds = getInitialBounds(displayLayout, task, deskId) if (canChangeTaskPosition(task)) { wct.setBounds(task.token, initialBounds) } } if (DesktopExperienceFlags.ENABLE_MULTIPLE_DESKTOPS_BACKEND.isTrue) { desksOrganizer.moveTaskToDesk(wct = wct, deskId = deskId, task = task) } else { Loading Loading @@ -4530,8 +4528,14 @@ class DesktopTasksController( } else { calculateDefaultDesktopTaskBounds(displayLayout) } if (DesktopModeFlags.ENABLE_CASCADING_WINDOWS.isTrue) { var hasLayoutGravityApplied = false if (!repository.isActiveTask(taskInfo.taskId)) { // Only apply layout gravity to new tasks in desk. val stableBounds = Rect() displayLayout.getStableBoundsForDesktopMode(stableBounds) hasLayoutGravityApplied = applyLayoutGravityIfNeeded(taskInfo, bounds, stableBounds) } if (DesktopModeFlags.ENABLE_CASCADING_WINDOWS.isTrue && !hasLayoutGravityApplied) { cascadeWindow( context, recentTasksController, Loading libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt +12 −8 Original line number Diff line number Diff line Loading @@ -1379,47 +1379,51 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase() } @Test fun addMoveToDeskTaskChanges_gravityLeft_noBoundsApplied() { fun addMoveToDeskTaskChanges_gravityLeft_gravityAppliedOnBounds() { setUpLandscapeDisplay() val stableBounds = Rect().also { displayLayout.getStableBoundsForDesktopMode(it) } val task = setUpFullscreenTask(gravity = Gravity.LEFT) val wct = WindowContainerTransaction() controller.addMoveToDeskTaskChanges(wct, task, deskId = 0) val finalBounds = findBoundsChange(wct, task) assertThat(finalBounds).isNull() assertThat(finalBounds!!.left).isEqualTo(stableBounds.left) } @Test fun addMoveToDeskTaskChanges_gravityRight_noBoundsApplied() { fun addMoveToDeskTaskChanges_gravityRight_gravityAppliedOnBounds() { setUpLandscapeDisplay() val stableBounds = Rect().also { displayLayout.getStableBoundsForDesktopMode(it) } val task = setUpFullscreenTask(gravity = Gravity.RIGHT) val wct = WindowContainerTransaction() controller.addMoveToDeskTaskChanges(wct, task, deskId = 0) val finalBounds = findBoundsChange(wct, task) assertThat(finalBounds).isNull() assertThat(finalBounds!!.right).isEqualTo(stableBounds.right) } @Test fun addMoveToDeskTaskChanges_gravityTop_noBoundsApplied() { fun addMoveToDeskTaskChanges_gravityTop_gravityAppliedOnBounds() { setUpLandscapeDisplay() val stableBounds = Rect().also { displayLayout.getStableBoundsForDesktopMode(it) } val task = setUpFullscreenTask(gravity = Gravity.TOP) val wct = WindowContainerTransaction() controller.addMoveToDeskTaskChanges(wct, task, deskId = 0) val finalBounds = findBoundsChange(wct, task) assertThat(finalBounds).isNull() assertThat(finalBounds!!.top).isEqualTo(stableBounds.top) } @Test fun addMoveToDeskTaskChanges_gravityBottom_noBoundsApplied() { fun addMoveToDeskTaskChanges_gravityBottom_gravityAppliedOnBounds() { setUpLandscapeDisplay() val stableBounds = Rect().also { displayLayout.getStableBoundsForDesktopMode(it) } val task = setUpFullscreenTask(gravity = Gravity.BOTTOM) val wct = WindowContainerTransaction() controller.addMoveToDeskTaskChanges(wct, task, deskId = 0) val finalBounds = findBoundsChange(wct, task) assertThat(finalBounds).isNull() assertThat(finalBounds!!.bottom).isEqualTo(stableBounds.bottom) } @Test Loading Loading
core/java/com/android/internal/policy/DesktopModeCompatUtils.java +27 −0 Original line number Diff line number Diff line Loading @@ -25,6 +25,7 @@ import android.annotation.NonNull; import android.content.pm.ActivityInfo; import android.content.res.Configuration; import android.graphics.Rect; import android.view.Gravity; import android.window.DesktopModeFlags; /** Loading Loading @@ -52,6 +53,32 @@ public final class DesktopModeCompatUtils { || info.isChangeEnabled(OVERRIDE_EXCLUDE_CAPTION_INSETS_FROM_APP_BOUNDS)); } /** * Applies a vertical and horizontal gravity on the inOutBounds in relation to the stableBounds. */ public static void applyLayoutGravity(int verticalGravity, int horizontalGravity, @NonNull Rect inOutBounds, @NonNull Rect stableBounds) { final int width = inOutBounds.width(); final int height = inOutBounds.height(); final float fractionOfHorizontalOffset = switch (horizontalGravity) { case Gravity.LEFT -> 0f; case Gravity.RIGHT -> 1f; default -> 0.5f; }; final float fractionOfVerticalOffset = switch (verticalGravity) { case Gravity.TOP -> 0f; case Gravity.BOTTOM -> 1f; default -> 0.5f; }; inOutBounds.offsetTo(stableBounds.left, stableBounds.top); final int xOffset = (int) (fractionOfHorizontalOffset * (stableBounds.width() - width)); final int yOffset = (int) (fractionOfVerticalOffset * (stableBounds.height() - height)); inOutBounds.offset(xOffset, yOffset); } /** * Returns the orientation of the given {@code rect}. */ Loading
libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTaskPosition.kt +11 −9 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ import android.graphics.Point import android.graphics.Rect import android.view.Gravity import com.android.internal.annotations.VisibleForTesting import com.android.internal.policy.DesktopModeCompatUtils.applyLayoutGravity import com.android.wm.shell.R import com.android.wm.shell.desktopmode.DesktopTaskPosition.BottomLeft import com.android.wm.shell.desktopmode.DesktopTaskPosition.BottomRight Loading Loading @@ -81,18 +82,19 @@ sealed class DesktopTaskPosition { abstract fun next(): DesktopTaskPosition } /** * If the app has specified horizontal or vertical gravity layout, don't change the task position * for cascading effect. */ fun canChangeTaskPosition(taskInfo: TaskInfo): Boolean { fun applyLayoutGravityIfNeeded(taskInfo: TaskInfo, bounds: Rect, stableBounds: Rect): Boolean { var horizontalGravity = 0 var verticalGravity = 0 taskInfo.topActivityInfo?.windowLayout?.let { val horizontalGravityApplied = it.gravity.and(Gravity.HORIZONTAL_GRAVITY_MASK) val verticalGravityApplied = it.gravity.and(Gravity.VERTICAL_GRAVITY_MASK) return horizontalGravityApplied == 0 && verticalGravityApplied == 0 horizontalGravity = it.gravity.and(Gravity.HORIZONTAL_GRAVITY_MASK) verticalGravity = it.gravity.and(Gravity.VERTICAL_GRAVITY_MASK) } if (verticalGravity > 0 || horizontalGravity > 0) { applyLayoutGravity(verticalGravity, horizontalGravity, bounds, stableBounds) return true } return false } /** Returns the current DesktopTaskPosition for a given window in the frame. */ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) Loading
libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt +9 −5 Original line number Diff line number Diff line Loading @@ -4438,10 +4438,8 @@ class DesktopTasksController( wct.setBounds(task.token, inheritedTaskBounds) } else { val initialBounds = getInitialBounds(displayLayout, task, deskId) if (canChangeTaskPosition(task)) { wct.setBounds(task.token, initialBounds) } } if (DesktopExperienceFlags.ENABLE_MULTIPLE_DESKTOPS_BACKEND.isTrue) { desksOrganizer.moveTaskToDesk(wct = wct, deskId = deskId, task = task) } else { Loading Loading @@ -4530,8 +4528,14 @@ class DesktopTasksController( } else { calculateDefaultDesktopTaskBounds(displayLayout) } if (DesktopModeFlags.ENABLE_CASCADING_WINDOWS.isTrue) { var hasLayoutGravityApplied = false if (!repository.isActiveTask(taskInfo.taskId)) { // Only apply layout gravity to new tasks in desk. val stableBounds = Rect() displayLayout.getStableBoundsForDesktopMode(stableBounds) hasLayoutGravityApplied = applyLayoutGravityIfNeeded(taskInfo, bounds, stableBounds) } if (DesktopModeFlags.ENABLE_CASCADING_WINDOWS.isTrue && !hasLayoutGravityApplied) { cascadeWindow( context, recentTasksController, Loading
libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt +12 −8 Original line number Diff line number Diff line Loading @@ -1379,47 +1379,51 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase() } @Test fun addMoveToDeskTaskChanges_gravityLeft_noBoundsApplied() { fun addMoveToDeskTaskChanges_gravityLeft_gravityAppliedOnBounds() { setUpLandscapeDisplay() val stableBounds = Rect().also { displayLayout.getStableBoundsForDesktopMode(it) } val task = setUpFullscreenTask(gravity = Gravity.LEFT) val wct = WindowContainerTransaction() controller.addMoveToDeskTaskChanges(wct, task, deskId = 0) val finalBounds = findBoundsChange(wct, task) assertThat(finalBounds).isNull() assertThat(finalBounds!!.left).isEqualTo(stableBounds.left) } @Test fun addMoveToDeskTaskChanges_gravityRight_noBoundsApplied() { fun addMoveToDeskTaskChanges_gravityRight_gravityAppliedOnBounds() { setUpLandscapeDisplay() val stableBounds = Rect().also { displayLayout.getStableBoundsForDesktopMode(it) } val task = setUpFullscreenTask(gravity = Gravity.RIGHT) val wct = WindowContainerTransaction() controller.addMoveToDeskTaskChanges(wct, task, deskId = 0) val finalBounds = findBoundsChange(wct, task) assertThat(finalBounds).isNull() assertThat(finalBounds!!.right).isEqualTo(stableBounds.right) } @Test fun addMoveToDeskTaskChanges_gravityTop_noBoundsApplied() { fun addMoveToDeskTaskChanges_gravityTop_gravityAppliedOnBounds() { setUpLandscapeDisplay() val stableBounds = Rect().also { displayLayout.getStableBoundsForDesktopMode(it) } val task = setUpFullscreenTask(gravity = Gravity.TOP) val wct = WindowContainerTransaction() controller.addMoveToDeskTaskChanges(wct, task, deskId = 0) val finalBounds = findBoundsChange(wct, task) assertThat(finalBounds).isNull() assertThat(finalBounds!!.top).isEqualTo(stableBounds.top) } @Test fun addMoveToDeskTaskChanges_gravityBottom_noBoundsApplied() { fun addMoveToDeskTaskChanges_gravityBottom_gravityAppliedOnBounds() { setUpLandscapeDisplay() val stableBounds = Rect().also { displayLayout.getStableBoundsForDesktopMode(it) } val task = setUpFullscreenTask(gravity = Gravity.BOTTOM) val wct = WindowContainerTransaction() controller.addMoveToDeskTaskChanges(wct, task, deskId = 0) val finalBounds = findBoundsChange(wct, task) assertThat(finalBounds).isNull() assertThat(finalBounds!!.bottom).isEqualTo(stableBounds.bottom) } @Test Loading