Make sure parent graphicsLayer is correctly propagated in Views implementation and software rendering mode
Views could re-execute the recorded draw lambda from a different flow so we have to correctly call withTracking every time the draw block is executed.
Test: new test in AndroidGraphicsLayerTest.kt
Change-Id: I48efb24b487d0da1189d0efd567eb266a7d06123
diff --git a/compose/ui/ui-graphics/src/androidInstrumentedTest/kotlin/androidx/compose/ui/graphics/layer/AndroidGraphicsLayerTest.kt b/compose/ui/ui-graphics/src/androidInstrumentedTest/kotlin/androidx/compose/ui/graphics/layer/AndroidGraphicsLayerTest.kt
index 658156b..2b840b3 100644
--- a/compose/ui/ui-graphics/src/androidInstrumentedTest/kotlin/androidx/compose/ui/graphics/layer/AndroidGraphicsLayerTest.kt
+++ b/compose/ui/ui-graphics/src/androidInstrumentedTest/kotlin/androidx/compose/ui/graphics/layer/AndroidGraphicsLayerTest.kt
@@ -1700,6 +1700,31 @@
}
@Test
+ fun testChildLayerHasReferenceToParentLayer() {
+ lateinit var layer1: GraphicsLayer
+ lateinit var layer2: GraphicsLayer
+ graphicsLayerTest(
+ block = { context ->
+ // creating new layers will also schedule a persistence pass in Handler
+ layer1 = context.createGraphicsLayer()
+ layer2 = context.createGraphicsLayer()
+ layer2.record(Density(1f), Ltr, IntSize(10, 10)) {
+ assertEquals(layer2, drawContext.graphicsLayer)
+ drawRect(Color.Red)
+ }
+ layer1.record(Density(1f), Ltr, IntSize(10, 10)) {
+ assertEquals(layer1, drawContext.graphicsLayer)
+ drawLayer(layer2)
+ }
+ drawLayer(layer1)
+ },
+ verify = {
+ // just verifying there is no crash
+ }
+ )
+ }
+
+ @Test
fun testCanvasTransformStateRestore() {
val bg = Color.White
val layerColor1 = Color.Red
diff --git a/compose/ui/ui-graphics/src/androidMain/kotlin/androidx/compose/ui/graphics/layer/AndroidGraphicsLayer.android.kt b/compose/ui/ui-graphics/src/androidMain/kotlin/androidx/compose/ui/graphics/layer/AndroidGraphicsLayer.android.kt
index b9b0424..857a07a 100644
--- a/compose/ui/ui-graphics/src/androidMain/kotlin/androidx/compose/ui/graphics/layer/AndroidGraphicsLayer.android.kt
+++ b/compose/ui/ui-graphics/src/androidMain/kotlin/androidx/compose/ui/graphics/layer/AndroidGraphicsLayer.android.kt
@@ -41,6 +41,7 @@
import androidx.compose.ui.graphics.drawscope.DefaultDensity
import androidx.compose.ui.graphics.drawscope.DrawScope
import androidx.compose.ui.graphics.drawscope.clipPath
+import androidx.compose.ui.graphics.drawscope.draw
import androidx.compose.ui.graphics.layer.LayerManager.Companion.isRobolectric
import androidx.compose.ui.graphics.nativeCanvas
import androidx.compose.ui.unit.Density
@@ -67,9 +68,9 @@
private val clipDrawBlock: DrawScope.() -> Unit = {
val path = outlinePath
if (usePathForClip && clip && path != null) {
- clipPath(path, block = drawBlock)
+ clipPath(path) { drawWithChildTracking() }
} else {
- drawBlock()
+ drawWithChildTracking()
}
}
@@ -432,10 +433,14 @@
}
private fun recordInternal() {
+ impl.record(density, layoutDirection, this, clipDrawBlock)
+ }
+
+ private fun DrawScope.drawWithChildTracking() {
childDependenciesTracker.withTracking(
onDependencyRemoved = { it.onRemovedFromParentLayer() }
) {
- impl.record(density, layoutDirection, this, clipDrawBlock)
+ drawBlock()
}
}
@@ -550,7 +555,9 @@
impl.draw(canvas)
} else {
val drawScope = softwareDrawScope ?: CanvasDrawScope().also { softwareDrawScope = it }
- drawScope.draw(density, layoutDirection, canvas, size.toSize(), drawBlock)
+ drawScope.draw(density, layoutDirection, canvas, size.toSize(), this) {
+ drawWithChildTracking()
+ }
}
if (willClipPath) {
diff --git a/compose/ui/ui-graphics/src/androidMain/kotlin/androidx/compose/ui/graphics/layer/GraphicsViewLayer.android.kt b/compose/ui/ui-graphics/src/androidMain/kotlin/androidx/compose/ui/graphics/layer/GraphicsViewLayer.android.kt
index 9ed246d..024dff6 100644
--- a/compose/ui/ui-graphics/src/androidMain/kotlin/androidx/compose/ui/graphics/layer/GraphicsViewLayer.android.kt
+++ b/compose/ui/ui-graphics/src/androidMain/kotlin/androidx/compose/ui/graphics/layer/GraphicsViewLayer.android.kt
@@ -437,7 +437,14 @@
val pictureCanvas = p.beginRecording(size.width, size.height)
try {
pictureCanvasHolder?.drawInto(pictureCanvas) {
- pictureDrawScope?.draw(density, layoutDirection, this, size.toSize(), block)
+ pictureDrawScope?.draw(
+ density,
+ layoutDirection,
+ this,
+ size.toSize(),
+ layer,
+ block
+ )
}
} finally {
p.endRecording()