Skip to content

Commit cae0284

Browse files
committed
CMP-9264 Expose showLayoutBounds API on ComposePanel
This exposes a showLayoutBounds property on ComposePanel (desktop only) that allows users to turn on or off the showLayoutBounds property on the root layout node owner(s). It appears that the property only fully takes effect after some interaction with the Compose UI, or a bounds change, even though we call renderImmediately() in the property setter. This might be a separate issue that is outside the scope of this change. The change mostly makes a few private fields internal to allow piping the property up to the ComposePanel, but has no public API impact. The new property is also annotated as experimental.
1 parent 4c05dc6 commit cae0284

File tree

6 files changed

+46
-6
lines changed

6 files changed

+46
-6
lines changed

compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/awt/ComposePanel.desktop.kt

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import androidx.compose.ui.LayerType
2323
import androidx.compose.ui.awt.RenderSettings.SkiaSurface
2424
import androidx.compose.ui.awt.RenderSettings.SwingGraphics
2525
import androidx.compose.ui.focus.FocusDirection
26+
import androidx.compose.ui.scene.BaseComposeScene
2627
import androidx.compose.ui.scene.ComposeContainer
2728
import androidx.compose.ui.semantics.SemanticsOwner
2829
import androidx.compose.ui.window.WindowExceptionHandler
@@ -171,7 +172,7 @@ class ComposePanel @ExperimentalComposeUiApi constructor(
171172

172173
override fun getPreferredSize(): Dimension? = if (isPreferredSizeSet) {
173174
super.getPreferredSize()
174-
} else {
175+
} else {
175176
_composeContainer?.preferredSize ?: Dimension(0, 0)
176177
}
177178

@@ -272,6 +273,7 @@ class ComposePanel @ExperimentalComposeUiApi constructor(
272273
focusManager.takeFocus(FocusDirection.Next)
273274
}
274275
}
276+
275277
else -> Unit
276278
}
277279
}
@@ -378,4 +380,25 @@ class ComposePanel @ExperimentalComposeUiApi constructor(
378380
fun renderImmediately() {
379381
_composeContainer?.renderImmediately()
380382
}
383+
384+
@ExperimentalComposeUiApi
385+
var showLayoutBounds: Boolean
386+
get() {
387+
val scene = _composeContainer?.mediator?.scene
388+
return if (scene is BaseComposeScene) {
389+
scene.showLayoutBounds
390+
} else {
391+
false
392+
}
393+
}
394+
set(value) {
395+
val scene = _composeContainer?.mediator?.scene
396+
if (scene is BaseComposeScene) {
397+
scene.showLayoutBounds = value
398+
} else {
399+
error("The scene must be a BaseComposeScene")
400+
}
401+
402+
renderImmediately()
403+
}
381404
}

compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/scene/ComposeContainer.desktop.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ internal class ComposeContainer(
127127
private val coroutineExceptionHandler = DesktopCoroutineExceptionHandler()
128128
private val coroutineContext = MainUIDispatcher + coroutineExceptionHandler
129129

130-
private val mediator = ComposeSceneMediator(
130+
internal val mediator = ComposeSceneMediator(
131131
container = container,
132132
windowContext = windowContext,
133133
exceptionHandler = {

compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/scene/ComposeSceneMediator.desktop.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -318,7 +318,7 @@ internal class ComposeSceneMediator(
318318
}
319319
}
320320

321-
private val scene by lazy { composeSceneFactory(this) }
321+
internal val scene by lazy { composeSceneFactory(this) }
322322
val focusManager get() = scene.focusManager
323323
var compositionLocalContext: CompositionLocalContext?
324324
get() = scene.compositionLocalContext

compose/ui/ui/src/skikoMain/kotlin/androidx/compose/ui/scene/BaseComposeScene.skiko.kt

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ import androidx.compose.runtime.Composable
2121
import androidx.compose.runtime.Composition
2222
import androidx.compose.runtime.CompositionContext
2323
import androidx.compose.runtime.CompositionLocalContext
24-
import androidx.compose.runtime.CompositionLocalProvider
2524
import androidx.compose.runtime.MonotonicFrameClock
2625
import androidx.compose.runtime.getValue
2726
import androidx.compose.runtime.mutableStateOf
@@ -40,8 +39,6 @@ import androidx.compose.ui.input.pointer.PointerType
4039
import androidx.compose.ui.input.rotary.RotaryScrollEvent
4140
import androidx.compose.ui.node.SnapshotInvalidationTracker
4241
import androidx.compose.ui.platform.GlobalSnapshotManager
43-
import androidx.compose.ui.platform.LocalPlatformScreenReader
44-
import androidx.compose.ui.platform.LocalPlatformWindowInsets
4542
import androidx.compose.ui.platform.ProvidePlatformCompositionLocals
4643
import androidx.compose.ui.util.trace
4744
import kotlin.concurrent.Volatile
@@ -308,6 +305,8 @@ internal abstract class BaseComposeScene(
308305
protected abstract fun measureAndLayout()
309306

310307
protected abstract fun draw(canvas: Canvas)
308+
309+
internal abstract var showLayoutBounds: Boolean
311310
}
312311

313312
internal val BaseComposeScene.semanticsOwnerListener

compose/ui/ui/src/skikoMain/kotlin/androidx/compose/ui/scene/CanvasLayersComposeScene.skiko.kt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ import androidx.compose.ui.input.pointer.PointerEventType
3838
import androidx.compose.ui.input.pointer.PointerInputEvent
3939
import androidx.compose.ui.input.pointer.PointerType
4040
import androidx.compose.ui.input.rotary.RotaryScrollEvent
41+
import androidx.compose.ui.node.InternalCoreApi
4142
import androidx.compose.ui.node.RootNodeOwner
4243
import androidx.compose.ui.platform.PlatformContext
4344
import androidx.compose.ui.platform.setContent
@@ -273,6 +274,13 @@ private class CanvasLayersComposeSceneImpl(
273274
forEachOwner { it.draw(canvas) }
274275
}
275276

277+
@OptIn(InternalCoreApi::class)
278+
override var showLayoutBounds: Boolean = false
279+
set(value) {
280+
field = value
281+
forEachOwner { it.owner.showLayoutBounds = value }
282+
}
283+
276284
/**
277285
* Find hovered owner for position of first pointer.
278286
*/
@@ -431,6 +439,8 @@ private class CanvasLayersComposeSceneImpl(
431439

432440
private fun onOwnerAppended(owner: RootNodeOwner) {
433441
semanticsOwnerListener?.onSemanticsOwnerAppended(owner.semanticsOwner)
442+
@OptIn(InternalCoreApi::class)
443+
owner.owner.showLayoutBounds = showLayoutBounds
434444
}
435445

436446
private fun onOwnerRemoved(owner: RootNodeOwner) {

compose/ui/ui/src/skikoMain/kotlin/androidx/compose/ui/scene/PlatformLayersComposeScene.skiko.kt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import androidx.compose.ui.graphics.Canvas
2626
import androidx.compose.ui.input.key.KeyEvent
2727
import androidx.compose.ui.input.pointer.PointerInputEvent
2828
import androidx.compose.ui.input.rotary.RotaryScrollEvent
29+
import androidx.compose.ui.node.InternalCoreApi
2930
import androidx.compose.ui.node.LayoutNode
3031
import androidx.compose.ui.node.RootNodeOwner
3132
import androidx.compose.ui.platform.setContent
@@ -192,6 +193,13 @@ private class PlatformLayersComposeSceneImpl(
192193
mainOwner.draw(canvas)
193194
}
194195

196+
override var showLayoutBounds: Boolean
197+
get() = mainOwner.owner.showLayoutBounds
198+
set(value) {
199+
@OptIn(InternalCoreApi::class)
200+
mainOwner.owner.showLayoutBounds = value
201+
}
202+
195203
private fun onOwnerAppended(owner: RootNodeOwner) {
196204
semanticsOwnerListener?.onSemanticsOwnerAppended(owner.semanticsOwner)
197205
}

0 commit comments

Comments
 (0)