zsui 0.3.0-alpha.2

Rust-first feature-gated native UI framework for Win32, AppKit, and Linux.
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
use serde::{Deserialize, Serialize};

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum PlatformName {
    Windows,
    Macos,
    Linux,
    Android,
    Unknown,
    Other(String),
}

impl PlatformName {
    pub fn current() -> Self {
        match crate::NativeUiPlatform::current_target() {
            Some(platform) => platform.into(),
            None => Self::Unknown,
        }
    }

    pub fn as_str(&self) -> &str {
        match self {
            Self::Windows => "windows",
            Self::Macos => "macos",
            Self::Linux => "linux",
            Self::Android => "android",
            Self::Unknown => "unknown",
            Self::Other(value) => value.as_str(),
        }
    }
}

impl From<crate::NativeUiPlatform> for PlatformName {
    fn from(platform: crate::NativeUiPlatform) -> Self {
        match platform {
            crate::NativeUiPlatform::Windows => Self::Windows,
            crate::NativeUiPlatform::Macos => Self::Macos,
            crate::NativeUiPlatform::Linux => Self::Linux,
            crate::NativeUiPlatform::Android => Self::Android,
        }
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum CapabilityStatus {
    Supported,
    Partial,
    Unsupported,
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct CapabilitySupport {
    pub status: CapabilityStatus,
    pub detail: String,
}

impl CapabilitySupport {
    pub fn supported(detail: impl Into<String>) -> Self {
        Self {
            status: CapabilityStatus::Supported,
            detail: detail.into(),
        }
    }

    pub fn partial(detail: impl Into<String>) -> Self {
        Self {
            status: CapabilityStatus::Partial,
            detail: detail.into(),
        }
    }

    pub fn unsupported(detail: impl Into<String>) -> Self {
        Self {
            status: CapabilityStatus::Unsupported,
            detail: detail.into(),
        }
    }

    pub fn accepts_declaration(&self) -> bool {
        !matches!(self.status, CapabilityStatus::Unsupported)
    }

    pub fn is_fully_supported(&self) -> bool {
        matches!(self.status, CapabilityStatus::Supported)
    }
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct HostCapabilities {
    pub platform: PlatformName,
    pub windows: CapabilitySupport,
    pub window_resizing: CapabilitySupport,
    pub window_decorations: CapabilitySupport,
    pub window_always_on_top: CapabilitySupport,
    pub window_transparency: CapabilitySupport,
    pub tray_or_status_menu: CapabilitySupport,
    pub menus: CapabilitySupport,
    pub global_hotkeys: CapabilitySupport,
    pub clipboard_text: CapabilitySupport,
    pub clipboard_image: CapabilitySupport,
    pub clipboard_files: CapabilitySupport,
    pub file_picker: CapabilitySupport,
    pub native_dialogs: CapabilitySupport,
    pub settings_pages: CapabilitySupport,
    pub auto_paste: CapabilitySupport,
}

impl HostCapabilities {
    pub fn all_supported(platform: PlatformName) -> Self {
        Self {
            platform,
            windows: CapabilitySupport::supported("window declarations are accepted"),
            window_resizing: CapabilitySupport::supported(
                "resizable and fixed-size windows are honored",
            ),
            window_decorations: CapabilitySupport::supported(
                "native window decorations are honored",
            ),
            window_always_on_top: CapabilitySupport::supported("always-on-top windows are honored"),
            window_transparency: CapabilitySupport::supported("transparent windows are honored"),
            tray_or_status_menu: CapabilitySupport::supported(
                "tray/status menu declarations are accepted",
            ),
            menus: CapabilitySupport::supported("menu declarations are accepted"),
            global_hotkeys: CapabilitySupport::supported("global hotkeys are accepted"),
            clipboard_text: CapabilitySupport::supported("text clipboard is available"),
            clipboard_image: CapabilitySupport::supported("image clipboard is available"),
            clipboard_files: CapabilitySupport::supported("file clipboard is available"),
            file_picker: CapabilitySupport::supported("native file picker is available"),
            native_dialogs: CapabilitySupport::supported("native dialogs are available"),
            settings_pages: CapabilitySupport::supported("settings page declarations are accepted"),
            auto_paste: CapabilitySupport::supported("native auto paste is available"),
        }
    }

    pub fn all_unsupported(platform: PlatformName) -> Self {
        let unsupported = CapabilitySupport::unsupported("not implemented by this host");
        Self {
            platform,
            windows: unsupported.clone(),
            window_resizing: unsupported.clone(),
            window_decorations: unsupported.clone(),
            window_always_on_top: unsupported.clone(),
            window_transparency: unsupported.clone(),
            tray_or_status_menu: unsupported.clone(),
            menus: unsupported.clone(),
            global_hotkeys: unsupported.clone(),
            clipboard_text: unsupported.clone(),
            clipboard_image: unsupported.clone(),
            clipboard_files: unsupported.clone(),
            file_picker: unsupported.clone(),
            native_dialogs: unsupported.clone(),
            settings_pages: unsupported.clone(),
            auto_paste: unsupported,
        }
    }

    pub fn current_platform_scaffold() -> Self {
        crate::desktop_runtime::scaffold_capabilities()
    }

    pub fn current_native_window_host() -> Self {
        crate::desktop_runtime::native_host_capabilities()
    }

    pub fn degraded_capabilities(&self) -> Vec<(&'static str, &CapabilitySupport)> {
        [
            ("windows", &self.windows),
            ("window_resizing", &self.window_resizing),
            ("window_decorations", &self.window_decorations),
            ("window_always_on_top", &self.window_always_on_top),
            ("window_transparency", &self.window_transparency),
            ("tray_or_status_menu", &self.tray_or_status_menu),
            ("menus", &self.menus),
            ("global_hotkeys", &self.global_hotkeys),
            ("clipboard_text", &self.clipboard_text),
            ("clipboard_image", &self.clipboard_image),
            ("clipboard_files", &self.clipboard_files),
            ("file_picker", &self.file_picker),
            ("native_dialogs", &self.native_dialogs),
            ("settings_pages", &self.settings_pages),
            ("auto_paste", &self.auto_paste),
        ]
        .into_iter()
        .filter(|(_, support)| !support.is_fully_supported())
        .collect()
    }

    pub fn windows_scaffold() -> Self {
        Self {
            platform: PlatformName::Windows,
            windows: CapabilitySupport::partial(
                "Win32 main-window hosts are expected; generic PlatformHost currently records declarations",
            ),
            window_resizing: CapabilitySupport::partial(
                "Win32 can create standard resizable windows; generic PlatformHost does not map styles yet",
            ),
            window_decorations: CapabilitySupport::partial(
                "Win32 can create decorated windows; generic PlatformHost does not map styles yet",
            ),
            window_always_on_top: CapabilitySupport::partial(
                "Win32 topmost windows exist; ZsuiHost style mapping is not wired yet",
            ),
            window_transparency: CapabilitySupport::partial(
                "Win32 transparency exists for selected hosts; ZsuiHost mapping is not wired yet",
            ),
            tray_or_status_menu: CapabilitySupport::partial(
                "Win32 tray/status APIs exist; generic PlatformHost currently records declarations",
            ),
            menus: CapabilitySupport::partial(
                "Win32 menu APIs exist; generic PlatformHost currently records declarations",
            ),
            global_hotkeys: CapabilitySupport::partial(
                "Win32 global hotkey APIs exist; generic PlatformHost currently records declarations",
            ),
            clipboard_text: CapabilitySupport::supported("text clipboard bridge is available"),
            clipboard_image: native_image_clipboard_support(),
            clipboard_files: CapabilitySupport::partial(
                "file clipboard support requires a native Windows host backend",
            ),
            file_picker: CapabilitySupport::partial(
                "Win32 file picker exists in the platform layer",
            ),
            native_dialogs: CapabilitySupport::partial("Win32 dialogs exist in the platform layer"),
            settings_pages: CapabilitySupport::partial("settings page specs are declarative"),
            auto_paste: CapabilitySupport::partial(
                "Windows paste-target code exists outside ZsuiHost",
            ),
        }
    }

    pub fn windows_native_window_host() -> Self {
        let mut capabilities = Self::windows_scaffold();
        capabilities.windows =
            CapabilitySupport::supported("Win32 native host creates main and quick windows");
        capabilities.window_resizing =
            CapabilitySupport::supported("Win32 window styles honor resizable and fixed windows");
        capabilities.window_decorations =
            CapabilitySupport::supported("Win32 window styles honor native decorations");
        capabilities.window_always_on_top =
            CapabilitySupport::supported("Win32 extended styles honor topmost windows");
        capabilities.window_transparency = CapabilitySupport::unsupported(
            "Win32 main window transparency is not mapped by the native window host yet",
        );
        capabilities.tray_or_status_menu = CapabilitySupport::partial(
            "Win32 status items, right-click callbacks, typed popup-menu commands and Explorer restart recovery are connected; target user-selection proof is still pending",
        );
        capabilities.menus = CapabilitySupport::supported(
            "Win32 window menus and HACCEL tables are RAII-owned and route typed Command values",
        );
        capabilities.file_picker = CapabilitySupport::supported(
            "Win32 common open-file dialog is connected through the native host",
        );
        capabilities.native_dialogs = CapabilitySupport::partial(
            "owner-bound MessageBoxW dialogs map typed levels, button sets and responses; target interaction proof is pending",
        );
        capabilities.clipboard_text = native_text_clipboard_support();
        capabilities.clipboard_image = native_image_clipboard_support();
        capabilities.clipboard_files =
            CapabilitySupport::unsupported("the native file clipboard service is not connected");
        capabilities
    }

    pub fn macos_scaffold() -> Self {
        Self {
            platform: PlatformName::Macos,
            windows: CapabilitySupport::partial(
                "the first-pass Winit window path exists; the AppKit backend is not connected",
            ),
            window_resizing: CapabilitySupport::partial(
                "the Winit path maps basic resize policy; AppKit verification is pending",
            ),
            window_decorations: CapabilitySupport::partial(
                "the Winit path maps native decorations; AppKit verification is pending",
            ),
            window_always_on_top: CapabilitySupport::partial(
                "the Winit path maps floating level; AppKit verification is pending",
            ),
            window_transparency: CapabilitySupport::unsupported(
                "transparent AppKit windows are not connected",
            ),
            tray_or_status_menu: CapabilitySupport::unsupported("NSStatusItem is not connected"),
            menus: CapabilitySupport::unsupported("NSMenu is not connected"),
            global_hotkeys: CapabilitySupport::unsupported(
                "global shortcut service is not wired in ZsuiHost",
            ),
            clipboard_text: CapabilitySupport::partial(
                "text clipboard requires the optional clipboard service; AppKit pasteboard is pending",
            ),
            clipboard_image: native_image_clipboard_support(),
            clipboard_files: CapabilitySupport::unsupported(
                "AppKit file pasteboard support is not connected",
            ),
            file_picker: CapabilitySupport::unsupported(
                "NSOpenPanel and NSSavePanel are not connected",
            ),
            native_dialogs: CapabilitySupport::unsupported("NSAlert is not connected"),
            settings_pages: CapabilitySupport::partial("settings page specs are declarative"),
            auto_paste: CapabilitySupport::unsupported("auto paste requires accessibility trust"),
        }
    }

    pub fn macos_native_window_host() -> Self {
        let mut capabilities = Self::macos_scaffold();
        if cfg!(feature = "macos-appkit") {
            capabilities.windows = CapabilitySupport::partial(
                "NSApplication/NSWindow lifecycle, draw-plan rendering, typed input, semantic focus rings and resize relayout are connected; target proof is pending",
            );
            capabilities.window_resizing = CapabilitySupport::partial(
                "actual NSView bounds rebuild shared layout, draw plans and input geometry; target resize artifacts are pending",
            );
            capabilities.window_decorations = CapabilitySupport::partial(
                "NSWindow titled and borderless style declarations are connected; target proof is pending",
            );
            capabilities.window_always_on_top = CapabilitySupport::partial(
                "NSFloatingWindowLevel is connected; target interaction proof is pending",
            );
            capabilities.tray_or_status_menu = CapabilitySupport::partial(
                "NSStatusItem and detached NSMenu resources are RAII-owned and command-routed by the AppKit event loop; fixed macOS 15 runtime smoke passed, while manual menu-bar interaction remains a release gate",
            );
        }
        capabilities.clipboard_text = if cfg!(all(feature = "macos-appkit", feature = "clipboard"))
        {
            CapabilitySupport::supported(
                "NSPasteboard UTF-8 text read/write is compiled by the optional clipboard service",
            )
        } else {
            CapabilitySupport::unsupported(
                "enable macos-appkit plus clipboard to compile the native AppKit clipboard service",
            )
        };
        capabilities.clipboard_image = if cfg!(all(feature = "macos-appkit", feature = "clipboard"))
        {
            CapabilitySupport::supported(
                "native NSPasteboard image transfer exposes validated RGBA pixels",
            )
        } else {
            CapabilitySupport::unsupported(
                "enable macos-appkit plus clipboard to compile native AppKit image transfer",
            )
        };
        capabilities.menus = if cfg!(feature = "macos-appkit") {
            CapabilitySupport::partial(
                "NSMenu/NSMenuItem installation and typed command polling are connected; AppKit host integration proof is pending",
            )
        } else {
            CapabilitySupport::unsupported(
                "enable macos-appkit to compile the native AppKit menu service",
            )
        };
        capabilities.file_picker = if cfg!(feature = "macos-appkit") {
            CapabilitySupport::partial(
                "NSOpenPanel and NSSavePanel are connected; target interaction proof is pending",
            )
        } else {
            CapabilitySupport::unsupported(
                "enable macos-appkit to compile NSOpenPanel and NSSavePanel services",
            )
        };
        capabilities.native_dialogs = if cfg!(feature = "macos-appkit") {
            CapabilitySupport::partial(
                "owner-bound NSAlert sheets map typed levels, platform action order and responses; target interaction proof is pending",
            )
        } else {
            CapabilitySupport::unsupported("enable macos-appkit to compile native NSAlert dialogs")
        };
        capabilities
    }

    pub fn linux_scaffold() -> Self {
        Self {
            platform: PlatformName::Linux,
            windows: CapabilitySupport::partial(
                "the first-pass Winit window path exists; the GTK4 backend is not connected",
            ),
            window_resizing: CapabilitySupport::partial(
                "the Winit path maps basic resize policy; GTK4 verification is pending",
            ),
            window_decorations: CapabilitySupport::partial(
                "the Winit path maps decorations; GTK4 and compositor verification are pending",
            ),
            window_always_on_top: CapabilitySupport::unsupported(
                "GTK4 always-on-top behavior is not connected and differs between Wayland and X11",
            ),
            window_transparency: CapabilitySupport::unsupported(
                "transparent GTK4 windows are not connected",
            ),
            tray_or_status_menu: CapabilitySupport::unsupported(
                "a Linux status-item service is not connected",
            ),
            menus: CapabilitySupport::unsupported("GTK/GIO menus are not connected"),
            global_hotkeys: CapabilitySupport::unsupported(
                "global shortcut support varies by display server",
            ),
            clipboard_text: CapabilitySupport::partial(
                "text clipboard requires the optional clipboard service; GTK clipboard is pending",
            ),
            clipboard_image: native_image_clipboard_support(),
            clipboard_files: CapabilitySupport::unsupported(
                "GTK file clipboard support is not connected",
            ),
            file_picker: CapabilitySupport::unsupported("GTK file chooser is not connected"),
            native_dialogs: CapabilitySupport::unsupported("GTK native dialogs are not connected"),
            settings_pages: CapabilitySupport::partial("settings page specs are declarative"),
            auto_paste: CapabilitySupport::partial(
                "xdotool/keytap path is backend and session dependent",
            ),
        }
    }

    pub fn linux_native_window_host() -> Self {
        let mut capabilities = Self::linux_scaffold();
        if cfg!(feature = "linux-direct-host") {
            capabilities.windows = CapabilitySupport::partial(
                "real Wayland/X11 windows, directly presented software rendering, typed input and resize-driven relayout are connected; target proof is pending",
            );
            capabilities.window_resizing = CapabilitySupport::partial(
                "native resize and scale-factor events rebuild shared layout, draw plans and input geometry; Wayland/X11 artifact proof is pending",
            );
            capabilities.window_decorations = CapabilitySupport::partial(
                "server/client compositor decorations and undecorated declarations are connected; target proof is pending",
            );
            capabilities.window_always_on_top = CapabilitySupport::partial(
                "native window-level declarations are connected; Wayland/X11 compositor proof is pending",
            );
            capabilities.window_transparency = CapabilitySupport::partial(
                "transparent surface declarations are connected; Wayland/X11 compositor proof is pending",
            );
        } else if cfg!(feature = "linux-gtk") {
            capabilities.windows = CapabilitySupport::partial(
                "GtkApplication/ApplicationWindow lifecycle, draw-plan rendering, typed input, semantic focus rings and allocation relayout are connected; target proof is pending",
            );
            capabilities.window_resizing = CapabilitySupport::partial(
                "actual DrawingArea allocation rebuilds shared layout, draw plans and input geometry; Wayland/X11 resize artifacts are pending",
            );
            capabilities.window_decorations = CapabilitySupport::partial(
                "GTK4 decorated and undecorated window declarations are connected; compositor proof is pending",
            );
        }
        capabilities.clipboard_text = if cfg!(all(
            feature = "linux-direct-host",
            feature = "clipboard"
        )) {
            CapabilitySupport::partial(
                "system UTF-8 text clipboard access is connected without GTK; Wayland/X11 ownership proof is pending",
            )
        } else if cfg!(all(feature = "linux-gtk", feature = "clipboard")) {
            CapabilitySupport::partial(
                "GdkClipboard UTF-8 text read/write is connected; Wayland/X11 host proof is pending",
            )
        } else {
            CapabilitySupport::unsupported(
                "enable linux-direct plus clipboard, or linux-gtk, to compile a Linux clipboard service",
            )
        };
        capabilities.clipboard_image = if cfg!(all(
            feature = "linux-direct-host",
            feature = "clipboard"
        )) {
            CapabilitySupport::partial(
                "native Wayland/X11 image clipboard transfer exposes validated RGBA pixels; compositor proof is pending",
            )
        } else if cfg!(all(feature = "linux-gtk", feature = "clipboard")) {
            CapabilitySupport::partial(
                "native GTK session image clipboard transfer exposes validated RGBA pixels; Wayland/X11 proof is pending",
            )
        } else {
            CapabilitySupport::unsupported(
                "enable linux-direct plus clipboard, or linux-gtk plus clipboard, to compile Linux image transfer",
            )
        };
        capabilities.menus = if cfg!(feature = "linux-direct-host") {
            CapabilitySupport::supported(
                "the owned desktop menu bar, popup navigation, accelerators and typed command routing are connected on the direct host",
            )
        } else if cfg!(all(
            feature = "linux-gtk",
            not(feature = "linux-direct-host")
        )) {
            CapabilitySupport::partial(
                "GMenu/SimpleAction installation and typed command polling are connected; GTK host integration proof is pending",
            )
        } else {
            CapabilitySupport::unsupported(
                "enable linux-direct or linux-gtk to compile a Linux desktop menu surface",
            )
        };
        capabilities.file_picker = if cfg!(feature = "linux-direct-host") {
            CapabilitySupport::partial(
                "XDG desktop portal open/save services are connected without GTK; target interaction proof is pending",
            )
        } else if cfg!(feature = "linux-gtk") {
            CapabilitySupport::partial(
                "GTK4 FileChooserNative open/save services are connected; Wayland/X11 interaction proof is pending",
            )
        } else {
            CapabilitySupport::unsupported(
                "enable linux-direct or linux-gtk to compile Linux file dialog services",
            )
        };
        capabilities.native_dialogs = if cfg!(feature = "linux-direct-host") {
            CapabilitySupport::partial(
                "typed message dialogs use the desktop-provided Zenity surface; provider availability and Wayland/X11 interaction proof are required",
            )
        } else if cfg!(feature = "linux-gtk") {
            CapabilitySupport::partial(
                "GTK 4.10 AlertDialog maps typed actions and responses; Wayland/X11 interaction proof is pending",
            )
        } else {
            CapabilitySupport::unsupported(
                "enable linux-direct or linux-gtk to compile Linux native message dialogs",
            )
        };
        capabilities
    }

    pub fn android_scaffold() -> Self {
        Self {
            platform: PlatformName::Android,
            windows: CapabilitySupport::partial(
                "Android Activity/native surface host is planned; generic PlatformHost records declarations",
            ),
            window_resizing: CapabilitySupport::unsupported(
                "Android phone/tablet surfaces do not map to desktop resize policy",
            ),
            window_decorations: CapabilitySupport::unsupported(
                "Android app chrome is owned by Activity/theme/system bars",
            ),
            window_always_on_top: CapabilitySupport::unsupported(
                "always-on-top requires Android overlay permissions and is not a normal app window",
            ),
            window_transparency: CapabilitySupport::partial(
                "transparent Activity surfaces depend on theme and compositor support",
            ),
            tray_or_status_menu: CapabilitySupport::unsupported(
                "Android has notifications/quick settings instead of a desktop tray",
            ),
            menus: CapabilitySupport::partial(
                "Android menu/action surfaces need a dedicated mobile host",
            ),
            global_hotkeys: CapabilitySupport::unsupported(
                "global shortcuts are not available to normal Android apps",
            ),
            clipboard_text: CapabilitySupport::partial(
                "Android ClipboardManager host is planned",
            ),
            clipboard_image: CapabilitySupport::partial(
                "Android image clipboard depends on URI/content-provider integration",
            ),
            clipboard_files: CapabilitySupport::partial(
                "Android file clipboard depends on content URI integration",
            ),
            file_picker: CapabilitySupport::partial(
                "Android Storage Access Framework host is planned",
            ),
            native_dialogs: CapabilitySupport::partial(
                "Android dialog host is planned",
            ),
            settings_pages: CapabilitySupport::partial(
                "settings page specs can be mapped to Android screens",
            ),
            auto_paste: CapabilitySupport::unsupported(
                "auto paste requires accessibility/input-method integration",
            ),
        }
    }

    pub fn android_native_window_host() -> Self {
        let mut capabilities = Self::android_scaffold();
        capabilities.windows = CapabilitySupport::unsupported(
            "NativeWindowHost does not yet own an Android Activity event loop",
        );
        capabilities
    }
}

fn native_text_clipboard_support() -> CapabilitySupport {
    if cfg!(feature = "clipboard") {
        CapabilitySupport::supported("the optional native text clipboard service is compiled")
    } else {
        CapabilitySupport::unsupported(
            "enable the clipboard feature to compile the native text clipboard service",
        )
    }
}

fn native_image_clipboard_support() -> CapabilitySupport {
    if cfg!(feature = "clipboard") {
        CapabilitySupport::supported(
            "the optional native clipboard service transfers validated RGBA images",
        )
    } else {
        CapabilitySupport::unsupported(
            "enable the clipboard feature to compile native RGBA image transfer",
        )
    }
}