Is there any elegant way to force Compose to repai...
# compose-desktop
s
Is there any elegant way to force Compose to repaint a region of the ui? I’m the maintainer of MapLibre Compose, and I’m working on a bug on macOS where a ghost image of the map remains after its been removed from the composition, until that region of the Compose UI is redrawn (say, through a window resize). Detailed context: I use a SwingPanel composable to integrate an AWT Canvas into my UI, and attach a CAMetalLayer to that canvas using jawt. The map is rendered with Metal to that layer. When the canvas is removed from the UI (handle
removeNotify
), I remove the metal layer in obj-c++ like so:
Copy code
CAMetalLayer* layer = (__bridge CAMetalLayer *)metalLayer.get();
[layer removeFromSuperlayer];
But an image of the map remains in the Compose UI, at least until something else is rendered there, or a resize forces the app to repaint. I already tried: • before removing the layer,
[layer.superLayer needsDisplay]
• in my canvas’s removeNotify:
parent.repaint()
and
SwingUtilities.getWindowAncestor(this).repaint()
and
SwingUtilities.getWindowAncestor(this).revalidate()
--- Just before hitting send, I tried this hack:
Copy code
// HACK: Force a repaint by resizing the window slightly to avoid a ghost map on macoOS.
val root = SwingUtilities.getWindowAncestor(this)
val oWidth = root.width
val oHeight = root.height
root.size = Dimension(oWidth + 1, oHeight + 1)
root.size = Dimension(oWidth, oHeight)
And well, it works, but it feels wrong. Is there a better way?
d
Well, I'm not an expert, and you also combine obj-c++ which makes it more complex to reproduce the issue. If you have a tiny program where I can reproduce, I would like to play with it. Why you can't use the native way to trigger a re-composition by changing a mutable value ? https://stackoverflow.com/a/73129228
Copy code
val text by remember { mutableStateOf("foo") }

key(text) {
    YourComposableFun(
        onClick = {
            text = "bar"
        }
    ) {

    }
}