Open XYZboom opened 5 months ago
I don't think that's a use-case we want to support.
What are you trying to achieve here? If you want to change the decorated state of the window, pass undecorated = newValue
to Window
.
I want to achieve the ability to switch window decoration state at runtime, but in Swing, I can only dispose of the window first and then re-show it. Like this:
val frame = JFrame()
frame.isUndecorated = true
frame.defaultCloseOperation = JFrame.EXIT_ON_CLOSE
val panel = JPanel()
frame.contentPane = panel
val button = JButton()
button.text = "Change Undecorated"
button.addMouseListener(object: MouseAdapter() {
override fun mouseClicked(e: MouseEvent?) {
frame.dispose()
frame.isUndecorated = !frame.isUndecorated
frame.isVisible = true
super.mouseClicked(e)
}
})
panel.add(button)
frame.setSize(300, 200)
frame.isVisible = true
but IllegalArgumentException when use compose
Reproduder:
fun main() = application {
var undecorated by remember { mutableStateOf(false) }
Window(
onCloseRequest = {},
undecorated = undecorated
) {
Button(
onClick = {
undecorated = !undecorated
}
) {
Text("Toggle Decorated")
}
}
}
The code (in setUndecoratedSafely
) acknowledges that it's not possible change the decorated flag while the window is showing. I don't know if it's possible to support this.
Java swing does not support to change decorate state when frame is showing.
A possible solution is: stackoverflow. But as shown above, it does not work on compose because ComposeContainer
was disposed and not recreate when re-show the window.
The document in setUndecoratedSafely
says that if isUndecorated
does not change, we can set isUndecorated
safely. But the effect of code is: if param value
!=
isUndecorated
, change the isUndecorated
. It's actually unsafe.
code here
@igordmn
The document in
setUndecoratedSafely
says that ifisUndecorated
does not change, we can setisUndecorated
safely. But the effect of code is: if paramvalue
!=
isUndecorated
, change theisUndecorated
. It's actually unsafe. code here @igordmn
Maybe we can dispose the window first and set its isUndecorated
. That's totally safe. Like solution metioned above
@elijah-semyonov I think want I need is re-show a disposed compose window, whether manually or automaticly. But neither of these two methods works, so l believe it's a bug in compose. Can you help add a bug tag, thanks!
Maybe need to support ComposeSceneLayer to open again after close
We could fix it by disposing and re-show the window when asked to change the decorated flag on it. To allow this we need to avoid disposing the ComposePanel
when the window is disposed, which is probably the right thing to do anyway.
Subject: [PATCH] Dispose and re-show window when undecorated flag changes.
---
Index: compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/util/Windows.desktop.kt
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/util/Windows.desktop.kt b/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/util/Windows.desktop.kt
--- a/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/util/Windows.desktop.kt (revision 7ca4551a1fa7aaf09e940b8bf6d75f876564ed21)
+++ b/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/util/Windows.desktop.kt (date 1712392967318)
@@ -157,7 +157,14 @@
*/
internal fun Frame.setUndecoratedSafely(value: Boolean) {
if (this.isUndecorated != value) {
- this.isUndecorated = value
+ if (isDisplayable) {
+ dispose()
+ this.isUndecorated = value
+ isVisible = true
+ }
+ else {
+ this.isUndecorated = value
+ }
}
}
Index: compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/awt/ComposeWindow.desktop.kt
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/awt/ComposeWindow.desktop.kt b/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/awt/ComposeWindow.desktop.kt
--- a/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/awt/ComposeWindow.desktop.kt (revision 7ca4551a1fa7aaf09e940b8bf6d75f876564ed21)
+++ b/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/awt/ComposeWindow.desktop.kt (date 1712392875993)
@@ -17,6 +17,7 @@
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalContext
+import androidx.compose.runtime.DisposableEffect
import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier
import androidx.compose.ui.input.key.KeyEvent
@@ -157,12 +158,13 @@
undecoratedWindowResizer.Content(
modifier = Modifier.layoutId("UndecoratedWindowResizer")
)
- }
- }
- override fun dispose() {
- composePanel.dispose()
- super.dispose()
+ DisposableEffect(Unit) {
+ onDispose {
+ composePanel.dispose()
+ }
+ }
+ }
}
override fun setUndecorated(value: Boolean) {
(same for DialogWindow
, of course)
We could fix it by disposing and re-show the window when asked to change the decorated flag on it. To allow this we need to avoid disposing the
ComposePanel
when the window is disposed, which is probably the right thing to do anyway.Subject: [PATCH] Dispose and re-show window when undecorated flag changes. --- Index: compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/util/Windows.desktop.kt IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== diff --git a/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/util/Windows.desktop.kt b/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/util/Windows.desktop.kt --- a/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/util/Windows.desktop.kt (revision 7ca4551a1fa7aaf09e940b8bf6d75f876564ed21) +++ b/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/util/Windows.desktop.kt (date 1712392967318) @@ -157,7 +157,14 @@ */ internal fun Frame.setUndecoratedSafely(value: Boolean) { if (this.isUndecorated != value) { - this.isUndecorated = value + if (isDisplayable) { + dispose() + this.isUndecorated = value + isVisible = true + } + else { + this.isUndecorated = value + } } } Index: compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/awt/ComposeWindow.desktop.kt IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== diff --git a/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/awt/ComposeWindow.desktop.kt b/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/awt/ComposeWindow.desktop.kt --- a/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/awt/ComposeWindow.desktop.kt (revision 7ca4551a1fa7aaf09e940b8bf6d75f876564ed21) +++ b/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/awt/ComposeWindow.desktop.kt (date 1712392875993) @@ -17,6 +17,7 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalContext +import androidx.compose.runtime.DisposableEffect import androidx.compose.ui.ExperimentalComposeUiApi import androidx.compose.ui.Modifier import androidx.compose.ui.input.key.KeyEvent @@ -157,12 +158,13 @@ undecoratedWindowResizer.Content( modifier = Modifier.layoutId("UndecoratedWindowResizer") ) - } - } - override fun dispose() { - composePanel.dispose() - super.dispose() + DisposableEffect(Unit) { + onDispose { + composePanel.dispose() + } + } + } } override fun setUndecorated(value: Boolean) {
(same for
DialogWindow
, of course)
Thanks a lot, it works. But issue 1448 occurs after this change.
So the problem is: the dispose
function in ComposeWindow
should only dispose resources temporarily but not permanently
Please check the following ticket on YouTrack for follow-ups to this issue. GitHub issues will be closed in the coming weeks.
Describe the bug When I try to re-display a window that has already been destroyed, the following exception message appears:
Affected platforms
Versions
To Reproduce Run this. I want set
isUndecorated
by click the button.Expected behavior Click the button and the
isUndecorated
of window changed. Works in java swing:Additional context stack: