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

Commit 6c3dcc39 authored by Xiaoqian (Daisy) Dai's avatar Xiaoqian (Daisy) Dai
Browse files

screen capture: fix region button box animation lag

The RegionBoxButton and RegionDimensionsPill lagged behind the main
selection box during drag operations. This was due to independent
positioning logic causing their updates to be out of sync with the
main box's graphicsLayer transform.

This change fixes the issue by wrapping the selection box, button,
and pill in a single parent Box that is moved with one
graphicsLayer. This ensures all elements move as a single, atomic
unit, eliminating the visual lag.

Bug: 437192780
Test: Manual
Flag: com.android.systemui.large_screen_screencapture

Change-Id: I268a1b2e344f7ff18539b97970be127d949597fd
parent 9a368d9b
Loading
Loading
Loading
Loading
+50 −45
Original line number Diff line number Diff line
@@ -28,7 +28,6 @@ import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.geometry.Rect
@@ -289,23 +288,29 @@ fun RegionBox(
        val borderStrokeWidth = 4.dp

        state.rect?.let { currentRect ->
            // A parent container for the region box and its associated UI. By applying the
            // graphicsLayer modifier here, all children will be moved together as a single unit,
            // ensuring their movements are perfectly synchronized.
            Box(
                modifier =
                    Modifier.graphicsLayer(
                        translationX = currentRect.left,
                        translationY = currentRect.top,
                    )
            ) {
                val boxWidthDp = with(density) { currentRect.width.toDp() }
                val boxHeightDp = with(density) { currentRect.height.toDp() }

                // The box that represents the region.
                Box(
                    modifier =
                    Modifier.graphicsLayer(
                            translationX = currentRect.left,
                            translationY = currentRect.top,
                        Modifier.size(boxWidthDp, boxHeightDp)
                            .border(borderStrokeWidth, MaterialTheme.colorScheme.onSurfaceVariant)
                )
                        .size(width = boxWidthDp, height = boxHeightDp)
                        .border(borderStrokeWidth, MaterialTheme.colorScheme.onSurfaceVariant),
                contentAlignment = Alignment.Center,
            ) {}

                // The button which initiates capturing the specified region of the screen. It is
            // positioned inside or outside the region box depending on the size of the region box.
                // positioned inside or outside the region box depending on the size of the region
                // box.
                RegionBoxButton(
                    text = buttonText,
                    icon = buttonIcon,
@@ -315,22 +320,21 @@ fun RegionBox(
                    onClick = onCaptureClick,
                )

            /** Vertical spacing in DP between the region box and the dimensions pill below it. */
                /** Vertical spacing in DP between the region box and the dimensions pill. */
                val pillVerticalSpacingDp = 16.dp
                val pillVerticalSpacingPx = with(density) { pillVerticalSpacingDp.toPx() }

                // A dimension pill that shows the region's dimensions.
                RegionDimensionsPill(
                    widthPx = currentRect.width.roundToInt(),
                    heightPx = currentRect.height.roundToInt(),
                    modifier =
                        Modifier.layout { measurable, _ ->
                        // Measure the pill's layout size, then center it horizontally based on the
                        // currentRect.
                            val dimensionsPillPlaceable = measurable.measure(Constraints())
                        val pillX =
                            currentRect.left +
                                (currentRect.width - dimensionsPillPlaceable.width) / 2
                        val pillY =
                            currentRect.bottom + with(density) { pillVerticalSpacingDp.toPx() }
                            // Center the pill horizontally relative to the region box's width, and
                            // position it vertically below the box.
                            val pillX = (currentRect.width - dimensionsPillPlaceable.width) / 2
                            val pillY = currentRect.height + pillVerticalSpacingPx
                            layout(dimensionsPillPlaceable.width, dimensionsPillPlaceable.height) {
                                dimensionsPillPlaceable.placeRelative(
                                    pillX.roundToInt(),
@@ -342,3 +346,4 @@ fun RegionBox(
            }
        }
    }
}
+3 −14
Original line number Diff line number Diff line
@@ -65,27 +65,16 @@ fun RegionBoxButton(

    // The translation of the button in the X direction.
    val targetTranslationX by
        animateFloatAsState(
            targetValue =
                if (isButtonOutside) {
                    // Position is centered horizontally, just above the box.
                    currentRect.left + (currentRect.width - buttonSize.width) / 2f
                } else {
                    // Position is centered inside the box.
                    currentRect.left + (currentRect.width - buttonSize.width) / 2f
                }
        )
        animateFloatAsState(targetValue = (currentRect.width - buttonSize.width) / 2f)

    // The translation of the button in the Y direction.
    val targetTranslationY by
        animateFloatAsState(
            targetValue =
                if (isButtonOutside) {
                    // Position is centered horizontally, just above the box.
                    currentRect.top - buttonSize.height
                    -buttonSize.height.toFloat()
                } else {
                    // Position is centered inside the box.
                    currentRect.top + (currentRect.height - buttonSize.height) / 2f
                    (currentRect.height - buttonSize.height) / 2f
                }
        )