Desktop
Enro runs on Compose Multiplatform for Desktop. main calls installNavigationController once, then opens each window through the returned controller.
Minimal install
fun main() {
val controller = MyComponent.installNavigationController(Unit)
controller.openWindow(
GenericRootWindow(
windowConfiguration = {
RootWindow.WindowConfiguration(
title = "My App",
onCloseRequest = { navigation.close() },
)
},
) {
val container = rememberNavigationContainer(
backstack = backstackOf(Home.asInstance()),
)
NavigationDisplay(state = container)
},
)
application {
EnroApplicationContent(controller)
}
}
installNavigationController(Unit)installs the controller for the process and returns theEnroController.controller.openWindow(...)registers a window with the controller. ThewindowConfigurationlambda returns the window’sRootWindow.WindowConfiguration: title, window state, visibility, key event handlers andonCloseRequest. The trailing lambda is the window’s Compose content.EnroApplicationContent(controller), called inside Compose Multiplatform’sapplication { }, renders every window registered with the controller.
The onCloseRequest lambda and the key event lambdas have a RootWindowScope receiver, and RootWindowScope.navigation is the window’s NavigationHandle. onCloseRequest = { navigation.close() } closes the window’s destination, which removes the window. navigation.close() is the default onCloseRequest.
Multi-window apps
Each window is a root navigation destination. controller.openWindow(...) opens a window from outside a destination. navigation.open(...) opens a window destination from another destination.
The desktop main file of the recipes app is an example with a MenuBar, key shortcuts and a complete WindowConfiguration.
A destination in its own window
rootWindowDestination binds a key to a window. navigation.open(key) opens the window. navigation.close() and navigation.complete(value) close the window. A window destination bound to a NavigationKey.WithResult<T> key returns a result with complete.
@NavigationDestination(NoteWindow::class)
val noteWindowDestination = rootWindowDestination<NoteWindow>(
windowConfiguration = {
RootWindow.WindowConfiguration(
title = "New note",
// The window's close button closes the destination without a result.
onCloseRequest = { navigation.close() },
)
},
) {
var text by remember { mutableStateOf("") }
MaterialTheme {
Surface(modifier = Modifier.fillMaxSize()) {
Column(
modifier = Modifier.padding(16.dp),
verticalArrangement = Arrangement.spacedBy(8.dp),
) {
Text("Note ${navigation.key.number}", style = MaterialTheme.typography.titleLarge)
TextField(value = text, onValueChange = { text = it })
// Completing closes the window and delivers the result.
Button(onClick = { navigation.complete(text) }) { Text("Save") }
Button(onClick = { navigation.close() }) { Text("Discard") }
}
}
}
}
To open an existing common destination in a window on desktop only, annotate a rootWindowDestination with @NavigationDestination.PlatformOverride(Key::class).
See the Multiple Windows recipe.
What Enro provides on desktop
- Each window hosts its own navigation containers and has its own
NavigationHandle. - Enro does not restore the backstack after a process restart on desktop. An app that requires the backstack after a restart must save and restore the backstack itself.
- The common API:
NavigationKey,NavigationKey.WithResult<T>,navigationHandle<T>(),registerForNavigationResult,NavigationDisplay, scene strategies, plugins, decorators.
See also
- Installation — installation on every platform.
- Recipes desktop main — an example with several windows, a
MenuBarand key shortcuts.