0
# Window Management
1
2
Window management in Compose Multiplatform for WASM/JS centers around the `CanvasBasedWindow` function, which creates the main application window that renders to an HTML5 Canvas element. This approach provides full control over the rendering surface while integrating seamlessly with web browsers.
3
4
## Core Window Management
5
6
### CanvasBasedWindow
7
8
The primary function for creating WASM/JS applications.
9
10
```kotlin { .api }
11
@OptIn(ExperimentalComposeUiApi::class)
12
fun CanvasBasedWindow(
13
canvasElementId: String? = null,
14
title: String = "Compose Application",
15
content: @Composable () -> Unit
16
)
17
```
18
19
**Parameters:**
20
- `canvasElementId`: ID of the HTML canvas element to render into. If null, uses default "ComposeTarget"
21
- `title`: Window title (affects browser tab title)
22
- `content`: Composable content to display in the window
23
24
**Usage:**
25
```kotlin { .api }
26
@OptIn(ExperimentalComposeUiApi::class)
27
fun main() {
28
CanvasBasedWindow("MyCanvas") {
29
MaterialTheme {
30
Text("Hello WASM!")
31
}
32
}
33
}
34
```
35
36
### Canvas Element Setup
37
38
The HTML document must contain a canvas element with the specified ID:
39
40
```html
41
<!DOCTYPE html>
42
<html>
43
<head>
44
<title>My Compose App</title>
45
<meta charset="UTF-8">
46
</head>
47
<body>
48
<canvas id="MyCanvas"></canvas>
49
<script src="your-app.js"></script>
50
</body>
51
</html>
52
```
53
54
## Application Lifecycle
55
56
### Initialization Sequence
57
58
1. **WASM Module Loading**: Browser loads and initializes the WASM module
59
2. **Canvas Acquisition**: Application locates and binds to the canvas element
60
3. **Compose Runtime Setup**: Initializes the Compose runtime system
61
4. **Content Rendering**: Begins rendering the composable content
62
63
### Main Function Pattern
64
65
```kotlin { .api }
66
@OptIn(ExperimentalComposeUiApi::class)
67
fun main() {
68
// Optional: Configure resources before window creation
69
configureWebResources {
70
resourcePathMapping { path -> "./$path" }
71
}
72
73
// Create the main application window
74
CanvasBasedWindow(
75
canvasElementId = "ComposeTarget",
76
title = "My Application"
77
) {
78
// Your application content
79
App()
80
}
81
}
82
```
83
84
## Window Configuration
85
86
### Canvas Element Targeting
87
88
**Default Behavior:**
89
```kotlin { .api }
90
CanvasBasedWindow("ComposeTarget") { /* content */ }
91
```
92
93
**Custom Canvas ID:**
94
```kotlin { .api }
95
CanvasBasedWindow("myCustomCanvas") { /* content */ }
96
```
97
98
**Auto-Detection (null ID):**
99
```kotlin { .api }
100
CanvasBasedWindow(canvasElementId = null) { /* content */ }
101
// Uses default "ComposeTarget" ID
102
```
103
104
### Title Management
105
106
The title parameter affects:
107
- Browser tab title
108
- Window identification in browser developer tools
109
- Accessibility tools
110
111
```kotlin { .api }
112
CanvasBasedWindow(
113
canvasElementId = "app",
114
title = "My WASM Application - ${BuildConfig.VERSION}"
115
) {
116
// Application content
117
}
118
```
119
120
## Experimental APIs
121
122
### ExperimentalComposeUiApi
123
124
All window management functions require the experimental API opt-in:
125
126
```kotlin { .api }
127
@file:OptIn(ExperimentalComposeUiApi::class)
128
129
import androidx.compose.ui.ExperimentalComposeUiApi
130
```
131
132
This annotation indicates that WASM support is experimental and APIs may change.
133
134
## Canvas Integration
135
136
### Canvas Properties
137
138
The canvas element receives these properties:
139
- **Full event handling**: Mouse, keyboard, touch events
140
- **Automatic sizing**: Canvas resizes with browser window
141
- **High DPI support**: Automatic pixel density detection
142
- **Focus management**: Keyboard focus and tab navigation
143
144
### CSS Styling
145
146
Style the canvas element for proper display:
147
148
```css
149
#ComposeTarget {
150
width: 100vw;
151
height: 100vh;
152
display: block;
153
margin: 0;
154
padding: 0;
155
}
156
157
body {
158
margin: 0;
159
padding: 0;
160
overflow: hidden;
161
}
162
```
163
164
## Error Handling
165
166
### Common Issues
167
168
**Canvas Not Found:**
169
```
170
Error: Canvas element with ID 'ComposeTarget' not found
171
```
172
- Ensure canvas element exists in HTML
173
- Verify ID matches exactly (case-sensitive)
174
- Check that script loads after canvas element
175
176
**WASM Initialization Failure:**
177
```
178
Error: Failed to instantiate WebAssembly module
179
```
180
- Verify browser supports WASM GC
181
- Check MIME type configuration
182
- Ensure WASM file is served correctly
183
184
**Resource Loading Issues:**
185
```
186
Error: Failed to load application resources
187
```
188
- Configure web resources before window creation
189
- Check resource path mappings
190
- Verify CORS configuration
191
192
### Debug Strategies
193
194
**Canvas Detection:**
195
```kotlin { .api }
196
// Check if canvas exists before creating window
197
val canvas = document.getElementById("ComposeTarget")
198
if (canvas == null) {
199
console.error("Canvas element not found!")
200
return
201
}
202
203
CanvasBasedWindow("ComposeTarget") { /* content */ }
204
```
205
206
**Console Logging:**
207
```kotlin { .api }
208
fun main() {
209
console.log("Starting WASM application...")
210
211
CanvasBasedWindow("ComposeTarget") {
212
console.log("Window content initialized")
213
App()
214
}
215
}
216
```
217
218
## Performance Considerations
219
220
### Rendering Optimization
221
222
- **Canvas sizing**: Use CSS for responsive sizing, avoid frequent resize operations
223
- **Event handling**: Minimize event listener overhead
224
- **Animation**: Use Compose animation APIs for optimal performance
225
226
### Memory Management
227
228
- **Canvas cleanup**: Browser automatically manages canvas memory
229
- **Event listeners**: Automatically cleaned up when window closes
230
- **Resource cleanup**: Use `DisposableEffect` for manual cleanup
231
232
```kotlin { .api }
233
@Composable
234
fun App() {
235
DisposableEffect(Unit) {
236
val cleanup = { /* cleanup code */ }
237
onDispose { cleanup() }
238
}
239
240
// App content
241
}
242
```
243
244
## Integration with Web Platform
245
246
### Browser Events
247
248
Canvas automatically receives and translates:
249
- **Mouse events**: Click, move, wheel
250
- **Keyboard events**: Key press, release, modifiers
251
- **Touch events**: Touch start, move, end
252
- **Focus events**: Focus in, focus out
253
254
### Accessibility
255
256
- **Screen reader support**: Canvas content is accessible
257
- **Keyboard navigation**: Full tab navigation support
258
- **High contrast**: Automatic high contrast mode detection
259
- **Zoom support**: Responds to browser zoom settings
260
261
### Browser API Access
262
263
Access browser APIs from window content:
264
265
```kotlin { .api }
266
@Composable
267
fun BrowserIntegration() {
268
LaunchedEffect(Unit) {
269
// Access browser window
270
val title = window.document.title
271
272
// Modify browser state
273
window.history.pushState(null, "", "/new-route")
274
275
// Use browser APIs
276
val userLanguage = window.navigator.language
277
}
278
}
279
```