Skip to content

Commit 515704a

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). The change mostly pipes the property up to the ComposePanel, but has no public API impact. The new property is also annotated as experimental. The Skiko RootNodeOwner's showLayoutBounds is now also a state, to cause a full recomposition when the value changes and see it reflected in the UI.
1 parent 4c05dc6 commit 515704a

File tree

10 files changed

+68
-5
lines changed

10 files changed

+68
-5
lines changed

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

Lines changed: 12 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.node.InternalCoreApi
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,13 @@ class ComposePanel @ExperimentalComposeUiApi constructor(
378380
fun renderImmediately() {
379381
_composeContainer?.renderImmediately()
380382
}
383+
384+
@InternalCoreApi
385+
var showLayoutBounds: Boolean = _composeContainer?.showLayoutBounds ?: false
386+
set(value) {
387+
// We're assuming we own the scene and thus this value, and nobody
388+
// else will change it from under us, so we never get out of sync.
389+
field = value
390+
_composeContainer?.showLayoutBounds = value
391+
}
381392
}

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import androidx.compose.ui.ExperimentalComposeUiApi
2121
import androidx.compose.ui.Modifier
2222
import androidx.compose.ui.input.key.KeyEvent
2323
import androidx.compose.ui.layout.layoutId
24+
import androidx.compose.ui.node.InternalCoreApi
2425
import androidx.compose.ui.semantics.SemanticsOwner
2526
import androidx.compose.ui.unit.Dp
2627
import androidx.compose.ui.window.FrameWindowScope
@@ -327,4 +328,13 @@ class ComposeWindow @ExperimentalComposeUiApi constructor(
327328

328329
override fun removeMouseWheelListener(listener: MouseWheelListener) =
329330
composePanel.removeMouseWheelListener(listener)
331+
332+
@InternalCoreApi
333+
var showLayoutBounds: Boolean
334+
get() {
335+
return composePanel.showLayoutBounds
336+
}
337+
set(value) {
338+
composePanel.showLayoutBounds = value
339+
}
330340
}

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import androidx.compose.ui.ComposeFeatureFlags
2222
import androidx.compose.ui.LayerType
2323
import androidx.compose.ui.Modifier
2424
import androidx.compose.ui.input.key.KeyEvent
25+
import androidx.compose.ui.node.InternalCoreApi
2526
import androidx.compose.ui.scene.ComposeContainer
2627
import androidx.compose.ui.window.LocalWindow
2728
import androidx.savedstate.SavedState
@@ -190,4 +191,13 @@ internal class ComposeWindowPanel(
190191
override fun removeMouseMotionListener(listener: MouseMotionListener) {
191192
contentComponent.removeMouseMotionListener(listener)
192193
}
194+
195+
@InternalCoreApi
196+
var showLayoutBounds: Boolean
197+
get() {
198+
return _composeContainer?.showLayoutBounds ?: false
199+
}
200+
set(value) {
201+
_composeContainer?.showLayoutBounds = value
202+
}
193203
}

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import androidx.compose.ui.awt.AwtEventListener
2525
import androidx.compose.ui.awt.AwtEventListeners
2626
import androidx.compose.ui.awt.RenderSettings
2727
import androidx.compose.ui.input.key.KeyEvent
28+
import androidx.compose.ui.node.InternalCoreApi
2829
import androidx.compose.ui.platform.DefaultArchitectureComponentsOwner
2930
import androidx.compose.ui.platform.PlatformContext
3031
import androidx.compose.ui.platform.PlatformWindowContext
@@ -176,6 +177,9 @@ internal class ComposeContainer(
176177
val preferredSize by mediator::preferredSize
177178
val semanticsOwners by mediator::semanticsOwners
178179

180+
@set:InternalCoreApi
181+
var showLayoutBounds by mediator::showLayoutBounds
182+
179183
private var isDisposed = false
180184
private var isDetached = true
181185
private var isMinimized = false

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ import androidx.compose.ui.input.pointer.PointerIcon
4343
import androidx.compose.ui.input.pointer.PointerKeyboardModifiers
4444
import androidx.compose.ui.input.pointer.PointerType
4545
import androidx.compose.ui.navigationevent.BackNavigationEventInput
46+
import androidx.compose.ui.node.InternalCoreApi
4647
import androidx.compose.ui.platform.AwtDragAndDropManager
4748
import androidx.compose.ui.platform.DefaultInputModeManager
4849
import androidx.compose.ui.platform.DelegateRootForTestListener
@@ -323,6 +324,12 @@ internal class ComposeSceneMediator(
323324
var compositionLocalContext: CompositionLocalContext?
324325
get() = scene.compositionLocalContext
325326
set(value) { scene.compositionLocalContext = value }
327+
var showLayoutBounds: Boolean
328+
get() = scene.showLayoutBounds
329+
@InternalCoreApi set(value) {
330+
scene.showLayoutBounds = value
331+
}
332+
326333

327334
/**
328335
* Provides the size of ComposeScene content inside infinity constraints

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -498,7 +498,7 @@ internal class RootNodeOwner(
498498
override val fontLoader = androidx.compose.ui.text.platform.FontLoader()
499499
override val fontFamilyResolver = createFontFamilyResolver()
500500
override val layoutDirection get() = _layoutDirection
501-
override var showLayoutBounds = false
501+
override var showLayoutBounds by mutableStateOf(false)
502502
@InternalCoreApi
503503
set
504504

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

Lines changed: 0 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

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+
override var showLayoutBounds: Boolean = false
278+
@InternalCoreApi
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
*/
@@ -560,6 +568,8 @@ private class CanvasLayersComposeSceneImpl(
560568
private var onKeyEvent: ((KeyEvent) -> Boolean)? = null
561569

562570
init {
571+
@OptIn(InternalCoreApi::class)
572+
owner.owner.showLayoutBounds = showLayoutBounds
563573
attachLayer(this)
564574
}
565575

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,4 +284,10 @@ sealed interface ComposeScene : AutoCloseable {
284284
* provided by the [androidx.compose.runtime.Recomposer] of the current scene.
285285
*/
286286
suspend fun withMonotonicFrameClock(block: suspend () -> Unit)
287+
288+
/**
289+
* Set the visual debug option that shows bounds for all nodes in the hierarchy.
290+
*/
291+
@set:InternalComposeUiApi
292+
var showLayoutBounds: Boolean
287293
}

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+
@InternalCoreApi
199+
set(value) {
200+
mainOwner.owner.showLayoutBounds = value
201+
}
202+
195203
private fun onOwnerAppended(owner: RootNodeOwner) {
196204
semanticsOwnerListener?.onSemanticsOwnerAppended(owner.semanticsOwner)
197205
}

0 commit comments

Comments
 (0)