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

Commit c3443f3e authored by Alp Yalcin's avatar Alp Yalcin
Browse files

[4/n] Create the new window from the relative touch point in users’ dragShadow

We want to preserve the same relative position of the touch point, as it was on the dragShadow, since it allows a better experience via positioning based on the user's finger.

Flag: com.android.window.flags.enable_interaction_dependent_tab_tearing_bounds
Bug: 436504714
Test: atest WMShellUnitTests:DesktopTasksControllerTest
Change-Id: I7e992d44b27f988419d60c548dc0b38777bd0b16
parent 33f6e24b
Loading
Loading
Loading
Loading
+51 −0
Original line number Diff line number Diff line
@@ -36,6 +36,8 @@ import android.content.res.Configuration.ORIENTATION_PORTRAIT
import android.graphics.Rect
import android.os.SystemProperties
import android.util.Size
import android.view.DragEvent
import android.window.DesktopExperienceFlags
import android.window.DesktopModeFlags
import com.android.internal.policy.DesktopModeCompatUtils
import com.android.wm.shell.ShellTaskOrganizer
@@ -199,6 +201,41 @@ fun calculateMaximizeBounds(displayLayout: DisplayLayout, taskInfo: RunningTaskI
    }
}

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

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

/**
 * Calculates the largest size that can fit in a given area while maintaining a specific aspect
 * ratio.
@@ -458,6 +495,20 @@ private fun isClosingExitingInstance(intentFlags: Int) =
    (intentFlags and FLAG_ACTIVITY_CLEAR_TASK) != 0 ||
        (intentFlags and FLAG_ACTIVITY_MULTIPLE_TASK) == 0

/**
 * 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,
 * which allows a better positioning based on user's finger.
 */
private fun calculateDropPositionOffset(
    dragOffsetX: Float,
    shadowWidth: Int,
    windowWidth: Int
): Int {
    val touchPointHorizontalRatio = dragOffsetX / shadowWidth.toFloat()
    return (windowWidth * touchPointHorizontalRatio).toInt()
}

/**
 * Calculates the desired initial bounds for applications in desktop windowing. This is done as a
 * scale of the screen bounds.
+2 −5
Original line number Diff line number Diff line
@@ -5605,14 +5605,11 @@ class DesktopTasksController(
                ) {
                    // Inherit parent's bounds.
                    newWindowBounds.set(taskInfo.configuration.windowConfiguration.bounds)

                } else {
                    newWindowBounds.set(calculateDefaultDesktopTaskBounds(displayLayout))
                }
                // Create the new window from the top-center at the drop point.
                newWindowBounds.offsetTo(
                        dragEvent.x.toInt() - (newWindowBounds.width() / 2),
                        dragEvent.y.toInt(),
                    )
                positionDragAndDropBounds(newWindowBounds, dragEvent)
            }
            IndicatorType.TO_SPLIT_RIGHT_INDICATOR -> {
                newWindowBounds.set(getSnapBounds(destinationDisplay, SnapPosition.RIGHT))