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

Commit 1f88409b authored by Hawkwood Glazier's avatar Hawkwood Glazier
Browse files

Adjust clock element size when bounds change

While compose measures the appropriate view size, it doesn't recompose
when the size of the underlying view changes. In order to signal to
compose that it should recalculate the positions of views, we hook into
the existing flow that tracks the size of the clock and use it to size
the compose element directly. This is only enforced as a minimum size to
avoid wrapping issues when the flow is at it's default value during
first composition, or in case it becomes out of sync for a frame.

This change also attempts to opportunistically fix a non-flexi bug, as
I'm dividing the two clock bounds flows for flexiglass anyway. There is
a latent edge-case where smartspace is incorrectly positioned for small
clock because it is being placed based on the measurements of the large
clock if a pending update to the isLargeClock flow is delayed and is
desynchronized from the onClockBoundsChanged flow. This potential issue
could be the root cause of b/436274234 but it has been difficult to
confirm since I haven't been able to isolate a reproduction.

Bug: 436274234
Bug: 438470065
Flag: com.android.systemui.scene_container
Test: Checked that date / weather / alarms animates
Change-Id: I96f7b7335f18c5adbb4ac7d2638b5e921a3dd440
parent ff09c42b
Loading
Loading
Loading
Loading
+23 −3
Original line number Diff line number Diff line
@@ -24,17 +24,19 @@ import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.heightIn
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.widthIn
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.res.dimensionResource
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.android.compose.animation.scene.ElementContentScope
import com.android.compose.modifiers.padding
import com.android.systemui.customization.clocks.R as clocksR
import com.android.systemui.keyguard.ui.viewmodel.KeyguardClockViewModel
import com.android.systemui.plugins.keyguard.VRectF
import com.android.systemui.plugins.keyguard.ui.composable.elements.LockscreenElement
import com.android.systemui.plugins.keyguard.ui.composable.elements.LockscreenElementKeys
import com.android.systemui.plugins.keyguard.ui.composable.elements.LockscreenElementKeys.Clock
@@ -67,6 +69,9 @@ constructor(
            val shouldDateWeatherBeBelowSmallClock: Boolean by
                keyguardClockViewModel.shouldDateWeatherBeBelowSmallClock
                    .collectAsStateWithLifecycle()
            val clockBounds: VRectF by
                keyguardClockViewModel.clockEventController.smallClockBounds
                    .collectAsStateWithLifecycle()

            // Horizontal Padding is handled internally within the SmartspaceCards element. This
            // makes the application here to other elements in the hierarchy slightly awkward.
@@ -79,7 +84,13 @@ constructor(
                        Modifier.padding(horizontal = xPadding)
                            .padding(top = dimensionResource(R.dimen.keyguard_clock_top_margin)),
                ) {
                    LockscreenElement(Clock.Small)
                    with(LocalDensity.current) {
                        LockscreenElement(
                            Clock.Small,
                            Modifier.widthIn(min = clockBounds.width.toDp())
                                .heightIn(min = clockBounds.height.toDp()),
                        )
                    }

                    if (!shouldDateWeatherBeBelowSmallClock) {
                        LockscreenElement(
@@ -113,6 +124,9 @@ constructor(
            val shouldDateWeatherBeBelowLargeClock: Boolean by
                keyguardClockViewModel.shouldDateWeatherBeBelowLargeClock
                    .collectAsStateWithLifecycle()
            val clockBounds: VRectF by
                keyguardClockViewModel.clockEventController.largeClockBounds
                    .collectAsStateWithLifecycle()

            // Horizontal Padding is handled internally within the SmartspaceCards element. This
            // makes the application here to other elements in the hierarchy slightly awkward.
@@ -157,7 +171,13 @@ constructor(
                        ),
                    modifier = Modifier.padding(horizontal = xPadding).fillMaxWidth().weight(1f),
                ) {
                    LockscreenElement(Clock.Large)
                    with(LocalDensity.current) {
                        LockscreenElement(
                            Clock.Large,
                            Modifier.widthIn(min = clockBounds.width.toDp())
                                .heightIn(min = clockBounds.height.toDp()),
                        )
                    }
                    if (shouldDateWeatherBeBelowLargeClock) {
                        LockscreenElement(Smartspace.DWA.LargeClock.Below)
                    }
+1 −1
Original line number Diff line number Diff line
@@ -314,7 +314,7 @@ open class ClockRegistry(
        val onComplete = endChangeTrace?.also { endChangeTrace = null } ?: return
        clock.eventListeners.attach(
            object : ClockEventListener {
                override fun onBoundsChanged(current: VRectF) {}
                override fun onBoundsChanged(currentBounds: VRectF, isLargeClock: Boolean) {}

                override fun onMaxSizeChanged(maxSize: VPointF, isLargeClock: Boolean) {}

+6 −2
Original line number Diff line number Diff line
@@ -112,7 +112,9 @@ class FlexClockController(

    override fun initialize(isDarkTheme: Boolean, dozeFraction: Float, foldFraction: Float) {
        smallClock.run {
            layerController.onViewBoundsChanged = { eventListeners.fire { onBoundsChanged(it) } }
            layerController.onViewBoundsChanged = {
                eventListeners.fire { onBoundsChanged(it, isLargeClock = false) }
            }
            layerController.onViewMaxSizeChanged = {
                eventListeners.fire { onMaxSizeChanged(it, isLargeClock = false) }
            }
@@ -124,7 +126,9 @@ class FlexClockController(
        }

        largeClock.run {
            layerController.onViewBoundsChanged = { eventListeners.fire { onBoundsChanged(it) } }
            layerController.onViewBoundsChanged = {
                eventListeners.fire { onBoundsChanged(it, isLargeClock = true) }
            }
            layerController.onViewMaxSizeChanged = {
                eventListeners.fire { onMaxSizeChanged(it, isLargeClock = true) }
            }
+1 −1
Original line number Diff line number Diff line
@@ -82,7 +82,7 @@ class ClockEventListeners {
}

interface ClockEventListener {
    fun onBoundsChanged(currentBounds: VRectF)
    fun onBoundsChanged(currentBounds: VRectF, isLargeClock: Boolean)

    fun onMaxSizeChanged(maxSize: VPointF, isLargeClock: Boolean)

+4 −3
Original line number Diff line number Diff line
@@ -247,7 +247,8 @@ constructor(
    private var largeClockOnSecondaryDisplay = false

    val dozeAmount = MutableStateFlow(0f)
    val onClockBoundsChanged = MutableStateFlow<VRectF>(VRectF.ZERO)
    val smallClockBounds = MutableStateFlow<VRectF>(VRectF.ZERO)
    val largeClockBounds = MutableStateFlow<VRectF>(VRectF.ZERO)
    val smallClockMaxSize = MutableStateFlow<VPointF>(VPointF.ZERO)
    val largeClockMaxSize = MutableStateFlow<VPointF>(VPointF.ZERO)

@@ -316,8 +317,8 @@ constructor(
        object : ClockEventListener {
            override fun onChangeComplete() {}

            override fun onBoundsChanged(currentBounds: VRectF) {
                onClockBoundsChanged.value = currentBounds
            override fun onBoundsChanged(currentBounds: VRectF, isLargeClock: Boolean) {
                (if (isLargeClock) largeClockBounds else smallClockBounds).value = currentBounds
            }

            override fun onMaxSizeChanged(maxSize: VPointF, isLargeClock: Boolean) {
Loading