# Desktop Compose APIs Catalog Complete reference for Compose Multiplatform Desktop-only APIs. ## Window Management ### application Root entry point for desktop apps. ```kotlin fun main() = application { Window(onCloseRequest = ::exitApplication) { Text("Hello Desktop") } } ``` ### Window Creates a window. ```kotlin Window( onCloseRequest: () -> Unit, state: WindowState = rememberWindowState(), visible: Boolean = true, title: String = "Untitled", icon: Painter? = null, undecorated: Boolean = false, transparent: Boolean = false, resizable: Boolean = true, enabled: Boolean = true, focusable: Boolean = true, alwaysOnTop: Boolean = false, onPreviewKeyEvent: ((KeyEvent) -> Boolean) = { false }, onKeyEvent: ((KeyEvent) -> Boolean) = { false }, content: @Composable FrameWindowScope.() -> Unit ) ``` **Example:** ```kotlin val windowState = rememberWindowState( width = 1200.dp, height = 800.dp, position = WindowPosition.Aligned(Alignment.Center) ) Window( onCloseRequest = ::exitApplication, state = windowState, title = "My App", resizable = true ) { // Content } ``` ### rememberWindowState Manages window size and position. ```kotlin @Composable fun rememberWindowState( placement: WindowPlacement = WindowPlacement.Floating, isMinimized: Boolean = false, position: WindowPosition = WindowPosition.PlatformDefault, width: Dp = Dp.Unspecified, height: Dp = Dp.Unspecified ): WindowState ``` **WindowPlacement:** - `Floating` - Normal window - `Maximized` - Fullscreen - `Fullscreen` - Fullscreen without decorations **WindowPosition:** - `PlatformDefault` - OS decides - `Aligned(alignment)` - Center, TopStart, etc. - `Absolute(x, y)` - Fixed position in pixels ### DialogWindow Modal dialog. ```kotlin DialogWindow( onCloseRequest: () -> Unit, state: DialogState = rememberDialogState(), visible: Boolean = true, title: String = "Dialog", icon: Painter? = null, undecorated: Boolean = false, transparent: Boolean = false, resizable: Boolean = true, enabled: Boolean = true, focusable: Boolean = true, content: @Composable DialogWindowScope.() -> Unit ) ``` **Example:** ```kotlin var showDialog by remember { mutableStateOf(false) } if (showDialog) { DialogWindow( onCloseRequest = { showDialog = false }, title = "Confirm" ) { Column(Modifier.padding(16.dp)) { Text("Are you sure?") Row { Button(onClick = { showDialog = false }) { Text("Cancel") } Button(onClick = { /* confirm */ }) { Text("OK") } } } } } ``` --- ## MenuBar ### MenuBar Native menu bar for windows. ```kotlin @Composable fun FrameWindowScope.MenuBar( content: @Composable MenuBarScope.() -> Unit ) ``` **Example:** ```kotlin Window(onCloseRequest = ::exitApplication) { MenuBar { Menu("File") { Item("New", onClick = { /* ... */ }) Item("Open", onClick = { /* ... */ }) Separator() Item("Quit", onClick = ::exitApplication) } Menu("Edit") { Item("Copy", onClick = { /* ... */ }) Item("Paste", onClick = { /* ... */ }) } } } ``` ### Menu Top-level menu. ```kotlin @Composable fun MenuBarScope.Menu( text: String, mnemonic: Char? = null, enabled: Boolean = true, content: @Composable MenuScope.() -> Unit ) ``` ### Item Menu item. ```kotlin @Composable fun MenuScope.Item( text: String, onClick: () -> Unit, shortcut: KeyShortcut? = null, mnemonic: Char? = null, enabled: Boolean = true, icon: Painter? = null ) ``` **With keyboard shortcut:** ```kotlin Item( text = "Save", onClick = { save() }, shortcut = KeyShortcut(Key.S, ctrl = true), icon = painterResource("save.png") ) ``` ### Separator Menu separator line. ```kotlin @Composable fun MenuScope.Separator() ``` ### CheckboxItem Toggleable menu item. ```kotlin @Composable fun MenuScope.CheckboxItem( text: String, checked: Boolean, onCheckedChange: (Boolean) -> Unit, shortcut: KeyShortcut? = null, mnemonic: Char? = null, enabled: Boolean = true ) ``` **Example:** ```kotlin var darkMode by remember { mutableStateOf(false) } Menu("View") { CheckboxItem( text = "Dark Mode", checked = darkMode, onCheckedChange = { darkMode = it }, shortcut = KeyShortcut(Key.D, ctrl = true) ) } ``` ### RadioButtonItem Radio button menu item. ```kotlin @Composable fun MenuScope.RadioButtonItem( text: String, selected: Boolean, onClick: () -> Unit, shortcut: KeyShortcut? = null, mnemonic: Char? = null, enabled: Boolean = true ) ``` --- ## System Tray ### Tray System tray icon with menu. ```kotlin @Composable fun ApplicationScope.Tray( icon: Painter, state: TrayState = rememberTrayState(), tooltip: String? = null, onAction: () -> Unit = {}, menu: @Composable MenuScope.() -> Unit = {} ) ``` **Example:** ```kotlin application { var isVisible by remember { mutableStateOf(true) } Tray( icon = painterResource("tray-icon.png"), tooltip = "My App", onAction = { isVisible = true }, menu = { Item("Show Window", onClick = { isVisible = true }) Separator() Item("Quit", onClick = ::exitApplication) } ) if (isVisible) { Window( onCloseRequest = { isVisible = false }, title = "App" ) { // Content } } } ``` ### rememberTrayState Manages tray state. ```kotlin @Composable fun rememberTrayState(): TrayState ``` --- ## Notifications ### Notification (via Tray) Show desktop notifications through tray. ```kotlin val trayState = rememberTrayState() Tray( icon = painterResource("icon.png"), state = trayState ) // Send notification LaunchedEffect(Unit) { trayState.sendNotification( Notification( title = "Message", message = "You have a new message", type = Notification.Type.Info ) ) } ``` **Notification types:** - `Info` - Information - `Warning` - Warning - `Error` - Error --- ## Keyboard ### KeyShortcut Keyboard shortcut definition. ```kotlin data class KeyShortcut( val key: Key, val ctrl: Boolean = false, val meta: Boolean = false, val alt: Boolean = false, val shift: Boolean = false ) ``` **Examples:** ```kotlin // Ctrl+S (Windows/Linux) KeyShortcut(Key.S, ctrl = true) // Cmd+S (macOS) KeyShortcut(Key.S, meta = true) // Ctrl+Shift+N KeyShortcut(Key.N, ctrl = true, shift = true) // Alt+F4 KeyShortcut(Key.F4, alt = true) ``` ### onPreviewKeyEvent / onKeyEvent Window-level keyboard handlers. ```kotlin Window( onCloseRequest = ::exitApplication, onPreviewKeyEvent = { event -> if (event.key == Key.Escape && event.type == KeyEventType.KeyDown) { // Handle Escape true // Consume event } else { false // Propagate } } ) { // Content } ``` --- ## Mouse ### PointerMoveFilter (Deprecated, use Modifier.pointerInput) ```kotlin Box( modifier = Modifier .pointerInput(Unit) { awaitPointerEventScope { while (true) { val event = awaitPointerEvent() // Handle mouse events } } } ) ``` ### Mouse cursor ```kotlin Box( modifier = Modifier.pointerHoverIcon( icon = PointerIcon(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)) ) ) { Text("Hover me") } ``` **Cursor types:** - `DEFAULT_CURSOR` - `HAND_CURSOR` - `TEXT_CURSOR` - `CROSSHAIR_CURSOR` - `WAIT_CURSOR` - `MOVE_CURSOR` - `E_RESIZE_CURSOR`, `W_RESIZE_CURSOR`, etc. --- ## Drag & Drop (Experimental) ### onExternalDrag Handle drag-and-drop from external sources. ```kotlin Box( modifier = Modifier .size(200.dp) .background(Color.LightGray) .onExternalDrag( onDragStart = { externalDragValue -> println("Drag started") }, onDrag = { externalDragValue -> println("Dragging: ${externalDragValue.dragData}") }, onDragExit = { println("Drag exited") }, onDrop = { externalDragValue -> val dragData = externalDragValue.dragData when (dragData) { is DragData.FilesList -> { println("Files dropped: ${dragData.readFiles()}") } is DragData.Text -> { println("Text dropped: ${dragData.readText()}") } else -> {} } } ) ) { Text("Drop files here", Modifier.align(Alignment.Center)) } ``` --- ## Resources ### painterResource Load images from resources. ```kotlin val icon = painterResource("icon.png") Icon( painter = icon, contentDescription = "App icon" ) ``` **Resource location:** `src/jvmMain/resources/` --- ## Platform Integration ### Desktop.getDesktop() (AWT) Access system desktop features (not Compose API, but commonly used). ```kotlin import java.awt.Desktop import java.net.URI // Open URL in browser if (Desktop.isDesktopSupported()) { Desktop.getDesktop().browse(URI("https://example.com")) } // Open file with default app Desktop.getDesktop().open(File("/path/to/file.pdf")) // Open email client Desktop.getDesktop().mail(URI("mailto:user@example.com")) ``` ### FileDialog (AWT) File picker dialogs. ```kotlin import java.awt.FileDialog import java.awt.Frame // Open file val fileDialog = FileDialog(Frame(), "Select file", FileDialog.LOAD) fileDialog.isVisible = true val selectedFile = fileDialog.file val directory = fileDialog.directory // Save file val saveDialog = FileDialog(Frame(), "Save file", FileDialog.SAVE) saveDialog.file = "document.txt" saveDialog.isVisible = true ``` --- ## SwingPanel (Interop) Embed Swing components in Compose. ```kotlin import androidx.compose.ui.awt.SwingPanel import javax.swing.JButton SwingPanel( factory = { JButton("Swing Button").apply { addActionListener { println("Swing button clicked") } } }, modifier = Modifier.size(200.dp, 50.dp) ) ``` --- ## ComposePanel (Reverse Interop) Embed Compose in Swing. ```kotlin import androidx.compose.ui.awt.ComposePanel import javax.swing.JFrame val frame = JFrame("Swing Frame") val composePanel = ComposePanel() composePanel.setContent { Text("Compose in Swing") } frame.contentPane.add(composePanel) frame.setSize(400, 300) frame.isVisible = true ``` --- ## Version Requirements - **Kotlin:** 2.0+ - **Compose Multiplatform:** 1.7.0+ - **JVM Target:** 11+ (recommend 21) **See also:** - [Official Desktop API docs](https://www.jetbrains.com/help/kotlin-multiplatform-dev/compose-desktop-components.html) - [Compose Multiplatform repo](https://github.com/JetBrains/compose-multiplatform)