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

Commit 34634d7f authored by Graciela Putri's avatar Graciela Putri
Browse files

Apply appBounds together with bounds in wct if eligible

Apply app bounds for activities that have excluded caption insets from
app bounds together with bounds change. This ensures configuration sent
to Core is correct, or app bounds will be using old configuration. For
resizing, resetting app bounds is enough as resize veil covers the
flickering.

Flag: EXEMPT bug fix
Fix: 403492326
Test: Open SCM permission app and drag around
      Drag to next display
      Resize
      atest DesktopTasksControllerTest
Change-Id: I95a884a961fd99c28c75c77f9350c6d85944a7b5
parent 5230bd5d
Loading
Loading
Loading
Loading
+27 −27
Original line number Original line Diff line number Diff line
@@ -207,37 +207,27 @@ fun calculateMaximizeBounds(displayLayout: DisplayLayout, taskInfo: RunningTaskI
}
}


/**
/**
 * Position the new window based on the drag event.
 * Position the new window based on the drag event. It uses the drag shadow to maintain the relative
 * It uses the drag shadow to maintain the relative position on the new window.
 * position on the new window. If shadow has anomaly, the new window is created from the top-center
 * If shadow has anomaly, the new window is created from the top-center at the drop point.
 * at the drop point.
 */
 */
fun positionDragAndDropBounds(
fun positionDragAndDropBounds(newBounds: Rect, dragEvent: DragEvent) {
    newBounds : Rect,
    dragEvent : DragEvent
) {
    val shadowSurface = dragEvent.dragSurface
    val shadowSurface = dragEvent.dragSurface
    if (DesktopExperienceFlags.ENABLE_INTERACTION_DEPENDENT_TAB_TEARING_BOUNDS.isTrue() &&
    if (
        DesktopExperienceFlags.ENABLE_INTERACTION_DEPENDENT_TAB_TEARING_BOUNDS.isTrue() &&
            shadowSurface != null &&
            shadowSurface != null &&
            shadowSurface.isValid &&
            shadowSurface.isValid &&
        shadowSurface.width != 0) {
            shadowSurface.width != 0
    ) {
        // Calculate the horizontal offset to maintain the touch point's relative
        // Calculate the horizontal offset to maintain the touch point's relative
        // position on the new window.
        // position on the new window.
        val dropOffset = calculateDropPositionOffset(
        val dropOffset =
            dragEvent.offsetX,
            calculateDropPositionOffset(dragEvent.offsetX, shadowSurface.width, newBounds.width())
            shadowSurface.width,
            newBounds.width()
        )
        // Position the new window based on the drop point and its relative offset.
        // Position the new window based on the drop point and its relative offset.
        newBounds.offsetTo(
        newBounds.offsetTo(dragEvent.x.toInt() - dropOffset, dragEvent.y.toInt())
            dragEvent.x.toInt() - dropOffset,
            dragEvent.y.toInt())

    } else {
    } else {
        // Position the new window to the top-center at the drop point.
        // Position the new window to the top-center at the drop point.
        newBounds.offsetTo(
        newBounds.offsetTo(dragEvent.x.toInt() - (newBounds.width() / 2), dragEvent.y.toInt())
            dragEvent.x.toInt() - (newBounds.width() / 2),
            dragEvent.y.toInt(),
        )
    }
    }
}
}


@@ -510,13 +500,13 @@ fun createActivityOptionsForStartTask(


/**
/**
 * Calculates the horizontal offset from the left edge of a new window to the user's touch point.
 * Calculates the horizontal offset from the left edge of a new window to the user's touch point.
 * This preserves the same relative position of the touch point as it was on the dragShadow,
 * This preserves the same relative position of the touch point as it was on the dragShadow, which
 * which allows a better positioning based on user's finger.
 * allows a better positioning based on user's finger.
 */
 */
private fun calculateDropPositionOffset(
private fun calculateDropPositionOffset(
    dragOffsetX: Float,
    dragOffsetX: Float,
    shadowWidth: Int,
    shadowWidth: Int,
    windowWidth: Int
    windowWidth: Int,
): Int {
): Int {
    val touchPointHorizontalRatio = dragOffsetX / shadowWidth.toFloat()
    val touchPointHorizontalRatio = dragOffsetX / shadowWidth.toFloat()
    return (windowWidth * touchPointHorizontalRatio).toInt()
    return (windowWidth * touchPointHorizontalRatio).toInt()
@@ -539,6 +529,16 @@ private fun positionInScreen(desiredSize: Size, stableBounds: Rect): Rect =
        offsetTo(offset.x, offset.y)
        offsetTo(offset.x, offset.y)
    }
    }


/**
 * Gets the freeform caption insets if task was eligible for exclude caption insets from app bounds
 * compatibility treatment. Returns 0 if no compatibility treatment was applied.
 */
val TaskInfo.freeformCaptionInsets: Int
    get() =
        configuration.windowConfiguration.appBounds?.let {
            it.top - configuration.windowConfiguration.bounds.top
        } ?: 0

/**
/**
 * Whether the activity's aspect ratio can be changed or if it should be maintained as if it was
 * Whether the activity's aspect ratio can be changed or if it should be maintained as if it was
 * unresizeable.
 * unresizeable.
+33 −8
Original line number Original line Diff line number Diff line
@@ -1024,9 +1024,8 @@ class DesktopTasksController(
        val excludedTasks =
        val excludedTasks =
            getFocusedNonDesktopTasks(DEFAULT_DISPLAY, userId).map { task -> task.taskId }
            getFocusedNonDesktopTasks(DEFAULT_DISPLAY, userId).map { task -> task.taskId }
        // Preserve focus state on reconnect, regardless if focused task is restored or not.
        // Preserve focus state on reconnect, regardless if focused task is restored or not.
        val globallyFocusedTask = shellTaskOrganizer.getRunningTaskInfo(
        val globallyFocusedTask =
            focusTransitionObserver.globallyFocusedTaskId
            shellTaskOrganizer.getRunningTaskInfo(focusTransitionObserver.globallyFocusedTaskId)
        )
        mainScope.launch {
        mainScope.launch {
            preservedTaskIdsByDeskId.forEach { (preservedDeskId, preservedTaskIds) ->
            preservedTaskIdsByDeskId.forEach { (preservedDeskId, preservedTaskIds) ->
                val newDeskId =
                val newDeskId =
@@ -2426,6 +2425,7 @@ class DesktopTasksController(
        bounds: Rect? = null,
        bounds: Rect? = null,
        transitionHandler: TransitionHandler? = null,
        transitionHandler: TransitionHandler? = null,
        enterReason: EnterReason,
        enterReason: EnterReason,
        captionInsets: Int = 0,
    ) {
    ) {
        logV("moveToDisplay: taskId=%d displayId=%d", task.taskId, displayId)
        logV("moveToDisplay: taskId=%d displayId=%d", task.taskId, displayId)
        if (task.displayId == displayId) {
        if (task.displayId == displayId) {
@@ -2492,6 +2492,28 @@ class DesktopTasksController(
                }
                }
                if (bounds != null) {
                if (bounds != null) {
                    wct.setBounds(task.token, bounds)
                    wct.setBounds(task.token, bounds)

                    val prevCaptionInsets = task.freeformCaptionInsets
                    if (prevCaptionInsets != 0) {
                        val appBounds =
                            Rect(bounds).apply {
                                if (captionInsets != 0) {
                                    this.top += captionInsets
                                } else {
                                    val captionInsetsDp =
                                        displayController
                                            .getDisplayLayout(task.getDisplayId())
                                            ?.pxToDp(prevCaptionInsets)
                                            ?.toInt() ?: 0
                                    val newDisplayLayout =
                                        displayController.getDisplayLayout(displayId)
                                    val insets =
                                        newDisplayLayout?.dpToPx(captionInsetsDp)?.toInt() ?: 0
                                    this.top += insets
                                }
                            }
                        wct.setAppBounds(task.token, appBounds)
                    }
                } else if (DesktopExperienceFlags.ENABLE_MOVE_TO_NEXT_DISPLAY_SHORTCUT.isTrue) {
                } else if (DesktopExperienceFlags.ENABLE_MOVE_TO_NEXT_DISPLAY_SHORTCUT.isTrue) {
                    applyFreeformDisplayChange(wct, task, displayId, destinationDeskId)
                    applyFreeformDisplayChange(wct, task, displayId, destinationDeskId)
                }
                }
@@ -5621,12 +5643,9 @@ class DesktopTasksController(
                    DesktopExperienceFlags.ENABLE_CONNECTED_DISPLAYS_WINDOW_DRAG.isTrue() &&
                    DesktopExperienceFlags.ENABLE_CONNECTED_DISPLAYS_WINDOW_DRAG.isTrue() &&
                        newDisplayId != taskInfo.getDisplayId() &&
                        newDisplayId != taskInfo.getDisplayId() &&
                        displayAreaInfo != null
                        displayAreaInfo != null
                val prevCaptionInsets = taskInfo.freeformCaptionInsets


                if (isCrossDisplayDrag) {
                if (isCrossDisplayDrag) {
                    val prevCaptionInsets =
                        taskInfo.configuration.windowConfiguration.appBounds?.let {
                            it.top - taskInfo.configuration.windowConfiguration.bounds.top
                        } ?: 0
                    val captionInsetsDp =
                    val captionInsetsDp =
                        displayController
                        displayController
                            .getDisplayLayout(taskInfo.getDisplayId())
                            .getDisplayLayout(taskInfo.getDisplayId())
@@ -5655,12 +5674,18 @@ class DesktopTasksController(
                        constrainedBounds,
                        constrainedBounds,
                        windowDragTransitionHandler,
                        windowDragTransitionHandler,
                        enterReason = EnterReason.APP_HANDLE_DRAG,
                        enterReason = EnterReason.APP_HANDLE_DRAG,
                        captionInsets = captionInsets,
                    )
                    )
                } else {
                } else {
                    // Update task bounds so that the task position will match the position of its
                    // Update task bounds so that the task position will match the position of its
                    // leash
                    // leash
                    val wct = WindowContainerTransaction()
                    val wct = WindowContainerTransaction()
                    wct.setBounds(taskInfo.token, destinationBounds)
                    wct.setBounds(taskInfo.token, destinationBounds)
                    if (prevCaptionInsets != 0) {
                        val appBounds =
                            Rect(destinationBounds).apply { this.top += prevCaptionInsets }
                        wct.setAppBounds(taskInfo.token, appBounds)
                    }
                    transitions.startTransition(TRANSIT_CHANGE, wct, windowDragTransitionHandler)
                    transitions.startTransition(TRANSIT_CHANGE, wct, windowDragTransitionHandler)
                }
                }
                releaseVisualIndicator()
                releaseVisualIndicator()
+6 −0
Original line number Original line Diff line number Diff line
@@ -39,6 +39,7 @@ import com.android.wm.shell.desktopmode.DesktopModeEventLogger.Companion.InputMe
import com.android.wm.shell.desktopmode.DesktopModeEventLogger.Companion.ResizeTrigger
import com.android.wm.shell.desktopmode.DesktopModeEventLogger.Companion.ResizeTrigger
import com.android.wm.shell.desktopmode.DesktopModeEventLogger.Companion.getInputMethodType
import com.android.wm.shell.desktopmode.DesktopModeEventLogger.Companion.getInputMethodType
import com.android.wm.shell.desktopmode.DesktopTasksController
import com.android.wm.shell.desktopmode.DesktopTasksController
import com.android.wm.shell.desktopmode.freeformCaptionInsets
import com.android.wm.shell.shared.annotations.ShellMainThread
import com.android.wm.shell.shared.annotations.ShellMainThread
import com.android.wm.shell.shared.desktopmode.DesktopState
import com.android.wm.shell.shared.desktopmode.DesktopState
import com.android.wm.shell.transition.Transitions
import com.android.wm.shell.transition.Transitions
@@ -316,6 +317,11 @@ class MultiDisplayVeiledResizeTaskPositioner(
                windowDecoration.updateResizeVeil(repositionTaskBounds)
                windowDecoration.updateResizeVeil(repositionTaskBounds)
                val wct = WindowContainerTransaction()
                val wct = WindowContainerTransaction()
                wct.setBounds(windowDecoration.taskInfo.token, repositionTaskBounds)
                wct.setBounds(windowDecoration.taskInfo.token, repositionTaskBounds)
                val captionInsets = windowDecoration.taskInfo.freeformCaptionInsets
                if (captionInsets != 0) {
                    // Reset app bounds if app bounds were overridden.
                    wct.setAppBounds(windowDecoration.taskInfo.token, null)
                }
                transitions.startTransition(WindowManager.TRANSIT_CHANGE, wct, this)
                transitions.startTransition(WindowManager.TRANSIT_CHANGE, wct, this)
            } else {
            } else {
                // If bounds haven't changed, perform necessary veil reset here as startAnimation
                // If bounds haven't changed, perform necessary veil reset here as startAnimation
+10 −0
Original line number Original line Diff line number Diff line
@@ -8800,9 +8800,12 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
        val task = setUpFreeformTask()
        val task = setUpFreeformTask()
        val spyController = spy(controller)
        val spyController = spy(controller)
        val mockSurface = mock(SurfaceControl::class.java)
        val mockSurface = mock(SurfaceControl::class.java)
        val captionInsets = 20
        val mockDisplayLayout = mock(DisplayLayout::class.java)
        val mockDisplayLayout = mock(DisplayLayout::class.java)
        whenever(displayController.getDisplayLayout(task.displayId)).thenReturn(mockDisplayLayout)
        whenever(displayController.getDisplayLayout(task.displayId)).thenReturn(mockDisplayLayout)
        whenever(mockDisplayLayout.stableInsets()).thenReturn(Rect(0, 100, 2000, 2000))
        whenever(mockDisplayLayout.stableInsets()).thenReturn(Rect(0, 100, 2000, 2000))
        task.configuration.windowConfiguration.appBounds =
            Rect(task.configuration.windowConfiguration.bounds).apply { this.top += captionInsets }
        spyController.onDragPositioningMove(
        spyController.onDragPositioningMove(
            task,
            task,
            mockSurface,
            mockSurface,
@@ -8827,12 +8830,14 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
                motionEvent,
                motionEvent,
            )
            )
        val rectAfterEnd = Rect(100, 50, 500, 1150)
        val rectAfterEnd = Rect(100, 50, 500, 1150)
        val appBoundsAfterEnd = Rect(rectAfterEnd).apply { this.top += captionInsets }
        verify(transitions)
        verify(transitions)
            .startTransition(
            .startTransition(
                eq(TRANSIT_CHANGE),
                eq(TRANSIT_CHANGE),
                Mockito.argThat { wct ->
                Mockito.argThat { wct ->
                    return@argThat wct.changes.any { (token, change) ->
                    return@argThat wct.changes.any { (token, change) ->
                        change.configuration.windowConfiguration.bounds == rectAfterEnd
                        change.configuration.windowConfiguration.bounds == rectAfterEnd
                        change.configuration.windowConfiguration.appBounds == appBoundsAfterEnd
                    }
                    }
                },
                },
                eq(windowDragTransitionHandler),
                eq(windowDragTransitionHandler),
@@ -8847,8 +8852,11 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
        val spyController = spy(controller)
        val spyController = spy(controller)
        val mockSurface = mock(SurfaceControl::class.java)
        val mockSurface = mock(SurfaceControl::class.java)
        val mockDisplayLayout = mock(DisplayLayout::class.java)
        val mockDisplayLayout = mock(DisplayLayout::class.java)
        val captionInsets = 20
        whenever(displayController.getDisplayLayout(task.displayId)).thenReturn(mockDisplayLayout)
        whenever(displayController.getDisplayLayout(task.displayId)).thenReturn(mockDisplayLayout)
        whenever(mockDisplayLayout.stableInsets()).thenReturn(Rect(0, 100, 2000, 2000))
        whenever(mockDisplayLayout.stableInsets()).thenReturn(Rect(0, 100, 2000, 2000))
        task.configuration.windowConfiguration.appBounds =
            Rect(task.configuration.windowConfiguration.bounds).apply { this.top += captionInsets }
        spyController.onDragPositioningMove(
        spyController.onDragPositioningMove(
            task,
            task,
            mockSurface,
            mockSurface,
@@ -8859,6 +8867,7 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
        )
        )
        val currentDragBounds = Rect(100, 200, 500, 1000)
        val currentDragBounds = Rect(100, 200, 500, 1000)
        val appBounds = Rect(currentDragBounds).apply { this.top += captionInsets }
        whenever(spyController.getVisualIndicator()).thenReturn(desktopModeVisualIndicator)
        whenever(spyController.getVisualIndicator()).thenReturn(desktopModeVisualIndicator)
        whenever(desktopModeVisualIndicator.updateIndicatorType(any(), anyOrNull()))
        whenever(desktopModeVisualIndicator.updateIndicatorType(any(), anyOrNull()))
            .thenReturn(DesktopModeVisualIndicator.IndicatorType.NO_INDICATOR)
            .thenReturn(DesktopModeVisualIndicator.IndicatorType.NO_INDICATOR)
@@ -8881,6 +8890,7 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
                Mockito.argThat { wct ->
                Mockito.argThat { wct ->
                    return@argThat wct.changes.any { (token, change) ->
                    return@argThat wct.changes.any { (token, change) ->
                        change.configuration.windowConfiguration.bounds == currentDragBounds
                        change.configuration.windowConfiguration.bounds == currentDragBounds
                        change.configuration.windowConfiguration.appBounds == appBounds
                    }
                    }
                },
                },
                eq(windowDragTransitionHandler),
                eq(windowDragTransitionHandler),
+4 −1
Original line number Original line Diff line number Diff line
@@ -59,7 +59,10 @@ class AppCompatSandboxingPolicy {
                // parent.
                // parent.
                appBounds = mActivityRecord.mResolveConfigHint.mParentAppBoundsOverride;
                appBounds = mActivityRecord.mResolveConfigHint.mParentAppBoundsOverride;
            }
            }
            if (!resolvedConfig.windowConfiguration.getBounds().isEmpty()) {
                // Only set if there is a resolved override config.
                resolvedConfig.windowConfiguration.setBounds(appBounds);
                resolvedConfig.windowConfiguration.setBounds(appBounds);
            }
            }
        }
        }
    }
    }
}