https://kotlinlang.org logo
Title
j

Jurriaan Mous

03/20/2023, 7:24 AM
Hi, I am new to compose and am creating a multiwindow/multidocument app, and I notice that when I remove a window with the current construct I am using, wrong windows get closed. How can I make sure the right window with state gets closed? I have all the state within the App component with remember statements. Or should I move up all window/app state to the application level and remove it from within the components to ensure the window uses the right state? I expected that I could maybe pass an id or something to the Window so it would all work correctly. Am I making wrong assumptions here, is this a bug, or am I missing something? Thanks!!
@OptIn(ExperimentalComposeUiApi::class)
fun main() = application {
    val windows = rememberSaveable { mutableStateOf(listOf(0)) }
    val newWindowId = rememberSaveable { mutableStateOf(1) }

    fun onClose(windowId: Int) {
        if (windows.value.isEmpty()) {
            exitApplication()
        }
        windows.value = windows.value.filter { it != windowId }
    }

    windows.value.map { windowId ->
        Window(onCloseRequest = { onClose(windowId) }, title = "Window") {
            MenuBar {
                Menu("File", mnemonic = 'F') {
                    Item(
                        "New Window",
                        onClick = {
                            windows.value = windows.value + newWindowId.value
                            newWindowId.value += 1
                        },
                        shortcut = KeyShortcut(Key.N, meta = true, alt = true)
                    )
                }
            }
            App()
        }
    }
}
I also tried passing the windowId as a string to App component and passing it internally with
rememberSavable(key=windowId)
but it is still not closing the right window and maintaining the right state.
m

Maik Liebing

03/20/2023, 8:08 AM
I'm quite new to compose and compose-desktop, so this might not be the best way to solve the issue. This is my code to draw all application windows
for (workspace in workspaces) {
    key(workspace.id) {
        WorkspaceWindow(...) { 
            ...
        }
    }
}
WorkspaceWindow
is the function to create my windows. So it is similar to the body of your
map
function. The important point here is the
key
function as it makes sure, you always get the same state for the same identifier. Without the key function closing one window might reposition/resize other windows as they get different states now (while the content is still the same. So in your case, you should still have the correct windowIds). Maybe this solves your issue too.
j

Jurriaan Mous

03/20/2023, 8:50 AM
Ah yes,
key()
function was indeed the secret ingredient which I was missing. It works now. Thanks!!!