Skip to content

Commit 02f343b

Browse files
authored
Check if setting the same size does not invalidate things (#2757)
Fix for the issue that was found during the investigation of CMP-4556 ## Release Notes N/A
1 parent 180f3e3 commit 02f343b

File tree

2 files changed

+43
-4
lines changed

2 files changed

+43
-4
lines changed

compose/ui/ui/src/skikoMain/kotlin/androidx/compose/ui/node/RootNodeOwner.skiko.kt

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -146,8 +146,10 @@ internal class RootNodeOwner(
146146
val semanticsOwner get() = owner.semanticsOwner
147147
var size: IntSize? = size
148148
set(value) {
149-
field = value
150-
onRootConstrainsChanged(value?.toConstraints())
149+
if (field != value) {
150+
field = value
151+
onRootConstrainsChanged(value?.toConstraints())
152+
}
151153
}
152154
var density by mutableStateOf(density)
153155

@@ -219,7 +221,7 @@ internal class RootNodeOwner(
219221
height = children.fastMaxOfOrDefault(0) { it.outerCoordinator.measuredHeight },
220222
)
221223
} finally {
222-
measureAndLayoutDelegate.updateRootConstraintsWithInfinityCheck(constraints)
224+
measureAndLayoutDelegate.updateRootConstraintsWithInfinityCheck(size?.toConstraints())
223225
}
224226
}
225227

compose/ui/ui/src/skikoTest/kotlin/androidx/compose/ui/node/RootNodeOwnerTest.kt

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,12 @@ import androidx.compose.ui.text.input.TextEditingScope
3131
import androidx.compose.ui.text.input.TextEditorState
3232
import androidx.compose.ui.text.input.TextFieldValue
3333
import androidx.compose.ui.unit.Density
34+
import androidx.compose.ui.unit.IntSize
3435
import androidx.compose.ui.unit.LayoutDirection
3536
import kotlin.coroutines.CoroutineContext
3637
import kotlin.coroutines.EmptyCoroutineContext
3738
import kotlin.test.Test
39+
import kotlin.test.assertEquals
3840
import kotlin.test.assertFalse
3941
import kotlin.test.assertTrue
4042
import kotlinx.coroutines.CoroutineScope
@@ -154,18 +156,53 @@ class RootNodeOwnerTest {
154156
assertTrue(keyboardShowCalled)
155157
assertTrue(keyboardHideCalled)
156158
}
159+
160+
@Test
161+
fun setSizeOnlyTriggersConstraintChangeWhenValueChanges() = runTest {
162+
var invalidationCount = 0
163+
164+
val owner = RootNodeOwner(
165+
snapshotInvalidationTracker = SnapshotInvalidationTracker {
166+
invalidationCount++
167+
}
168+
)
169+
170+
// Set the initial size
171+
owner.size = IntSize(100, 100)
172+
val initialCount = invalidationCount
173+
174+
// Setting the same size should not trigger invalidation
175+
owner.size = IntSize(100, 100)
176+
177+
// Count should remain the same
178+
assertEquals(invalidationCount, initialCount)
179+
180+
// Setting a different size should trigger invalidation
181+
owner.size = IntSize(200, 200)
182+
183+
// Count should increase
184+
assertTrue(invalidationCount > initialCount)
185+
val afterChangeCount = invalidationCount
186+
187+
// Setting the same size again should not trigger another invalidation
188+
owner.size = IntSize(200, 200)
189+
190+
// Count should remain the same
191+
assertEquals(invalidationCount, afterChangeCount)
192+
}
157193
}
158194

159195
private fun RootNodeOwner(
160196
coroutineContext: CoroutineContext = EmptyCoroutineContext,
161197
platformContext: PlatformContext = PlatformContext.Empty(),
198+
snapshotInvalidationTracker: SnapshotInvalidationTracker = SnapshotInvalidationTracker {},
162199
) = RootNodeOwner(
163200
density = Density(1f),
164201
layoutDirection = LayoutDirection.Ltr,
165202
size = null,
166203
coroutineContext = coroutineContext,
167204
platformContext = platformContext,
168-
snapshotInvalidationTracker = SnapshotInvalidationTracker {},
205+
snapshotInvalidationTracker = snapshotInvalidationTracker,
169206
inputHandler = ComposeSceneInputHandler(
170207
prepareForPointerInputEvent = {},
171208
processPointerInputEvent = { PointerEventResult(false) },

0 commit comments

Comments
 (0)