Skip to main content

affineui_sys/
lib.rs

1//! Raw FFI bindings to the AffineUI C ABI.
2//!
3//! Hand-written against `include/affineui/c_api.h` and
4//! `include/affineui/c_api_app.h` (docs/LANGUAGE_BINDINGS.md §4.1 explains
5//! why these are hand-written rather than bindgen-generated). Names, enum
6//! values, and struct layouts mirror the headers exactly; the headers are
7//! the source of truth and the C ABI version gate
8//! ([`affineui_c_abi_version`]) protects against drift at load time.
9//!
10//! Everything here is `unsafe` and 1:1; use the `affineui` crate for the
11//! safe, idiomatic surface.
12
13#![allow(non_camel_case_types)]
14#![no_std]
15
16use core::ffi::{c_char, c_float, c_int, c_void};
17
18pub const AFFINEUI_C_ABI_VERSION: c_int = 1;
19
20// ── Opaque handles ───────────────────────────────────────────────────
21
22macro_rules! opaque {
23    ($name:ident) => {
24        #[repr(C)]
25        pub struct $name {
26            _private: [u8; 0],
27            _marker: core::marker::PhantomData<(*mut u8, core::marker::PhantomPinned)>,
28        }
29    };
30}
31
32opaque!(affineui_ui);
33opaque!(affineui_app);
34opaque!(affineui_document);
35opaque!(affineui_view);
36opaque!(affineui_widget);
37
38// ── Shared enums (values locked to the C header) ─────────────────────
39
40pub const AFFINEUI_EVENT_NONE: c_int = 0;
41pub const AFFINEUI_EVENT_MOUSE_MOVE: c_int = 1;
42pub const AFFINEUI_EVENT_MOUSE_DOWN: c_int = 2;
43pub const AFFINEUI_EVENT_MOUSE_UP: c_int = 3;
44pub const AFFINEUI_EVENT_MOUSE_WHEEL: c_int = 4;
45pub const AFFINEUI_EVENT_KEY_DOWN: c_int = 5;
46pub const AFFINEUI_EVENT_KEY_UP: c_int = 6;
47pub const AFFINEUI_EVENT_TEXT_INPUT: c_int = 7;
48pub const AFFINEUI_EVENT_RESIZE: c_int = 8;
49pub const AFFINEUI_EVENT_FOCUS_LOST: c_int = 9;
50pub const AFFINEUI_EVENT_FOCUS_GAINED: c_int = 10;
51
52pub const AFFINEUI_MOUSE_LEFT: c_int = 0;
53pub const AFFINEUI_MOUSE_RIGHT: c_int = 1;
54pub const AFFINEUI_MOUSE_MIDDLE: c_int = 2;
55
56// affineui_key: 0..=11 named keys, 12..=37 letters A..Z, 38..=47 digits.
57pub const AFFINEUI_KEY_UNKNOWN: c_int = 0;
58pub const AFFINEUI_KEY_ESCAPE: c_int = 1;
59pub const AFFINEUI_KEY_TAB: c_int = 2;
60pub const AFFINEUI_KEY_ENTER: c_int = 3;
61pub const AFFINEUI_KEY_BACKSPACE: c_int = 4;
62pub const AFFINEUI_KEY_DELETE: c_int = 5;
63pub const AFFINEUI_KEY_ARROW_LEFT: c_int = 6;
64pub const AFFINEUI_KEY_ARROW_RIGHT: c_int = 7;
65pub const AFFINEUI_KEY_ARROW_UP: c_int = 8;
66pub const AFFINEUI_KEY_ARROW_DOWN: c_int = 9;
67pub const AFFINEUI_KEY_HOME: c_int = 10;
68pub const AFFINEUI_KEY_END: c_int = 11;
69pub const AFFINEUI_KEY_A: c_int = 12;
70pub const AFFINEUI_KEY_Z: c_int = 37;
71pub const AFFINEUI_KEY_DIGIT0: c_int = 38;
72pub const AFFINEUI_KEY_DIGIT9: c_int = 47;
73
74pub const AFFINEUI_THEME_PLAIN: c_int = 0;
75pub const AFFINEUI_THEME_BOOTSTRAP: c_int = 1;
76pub const AFFINEUI_THEME_DECIUS: c_int = 2;
77
78pub const AFFINEUI_WIDGET_NONE: c_int = -1;
79pub const AFFINEUI_WIDGET_ROOT: c_int = 0;
80pub const AFFINEUI_WIDGET_CONTAINER: c_int = 1;
81pub const AFFINEUI_WIDGET_TEXT: c_int = 2;
82pub const AFFINEUI_WIDGET_RAW_HTML: c_int = 3;
83pub const AFFINEUI_WIDGET_HEADING: c_int = 4;
84pub const AFFINEUI_WIDGET_PANEL: c_int = 5;
85pub const AFFINEUI_WIDGET_BUTTON: c_int = 6;
86pub const AFFINEUI_WIDGET_CHECKBOX: c_int = 7;
87pub const AFFINEUI_WIDGET_SLIDER: c_int = 8;
88pub const AFFINEUI_WIDGET_KNOB: c_int = 9;
89pub const AFFINEUI_WIDGET_TEXT_INPUT: c_int = 10;
90pub const AFFINEUI_WIDGET_TEXT_AREA: c_int = 11;
91pub const AFFINEUI_WIDGET_DROPDOWN: c_int = 12;
92pub const AFFINEUI_WIDGET_BUTTON_GROUP: c_int = 13;
93pub const AFFINEUI_WIDGET_VIRTUAL_LIST: c_int = 14;
94pub const AFFINEUI_WIDGET_CARD: c_int = 15;
95
96// GPU backend / pixel format (embedded mode).
97pub const AFFINEUI_GPU_D3D11: c_int = 0;
98pub const AFFINEUI_GPU_METAL: c_int = 1;
99pub const AFFINEUI_GPU_GL: c_int = 2;
100pub const AFFINEUI_GPU_WGPU: c_int = 3;
101
102pub const AFFINEUI_FORMAT_DEFAULT: c_int = 0;
103pub const AFFINEUI_FORMAT_RGBA8: c_int = 1;
104pub const AFFINEUI_FORMAT_BGRA8: c_int = 2;
105pub const AFFINEUI_FORMAT_DEPTH: c_int = 3;
106pub const AFFINEUI_FORMAT_DEPTH_STENCIL: c_int = 4;
107
108pub const AFFINEUI_LOG_DEBUG: c_int = 0;
109pub const AFFINEUI_LOG_INFO: c_int = 1;
110pub const AFFINEUI_LOG_WARN: c_int = 2;
111pub const AFFINEUI_LOG_ERROR: c_int = 3;
112
113// ── Shared value structs ─────────────────────────────────────────────
114
115#[repr(C)]
116#[derive(Clone, Copy, Debug)]
117pub struct affineui_event {
118    pub r#type: c_int,
119    pub x: c_int,
120    pub y: c_int,
121    pub button: c_int,
122    pub wheel_dx: c_float,
123    pub wheel_dy: c_float,
124    pub key: c_int,
125    pub key_code: c_int,
126    pub text: *const c_char,
127    pub shift: c_int,
128    pub ctrl: c_int,
129    pub alt: c_int,
130    pub super_key: c_int,
131}
132
133#[repr(C)]
134#[derive(Clone, Copy, Debug, Default)]
135pub struct affineui_color {
136    pub r: u8,
137    pub g: u8,
138    pub b: u8,
139    pub a: u8,
140}
141
142#[repr(C)]
143#[derive(Clone, Copy, Debug, Default)]
144pub struct affineui_dispatch_result {
145    pub redraw_requested: c_int,
146    pub invalidate_view: c_int,
147    pub defer_widget_changes: c_int,
148    pub layout_changed: c_int,
149}
150
151#[repr(C)]
152#[derive(Clone, Copy, Debug)]
153pub struct affineui_app_config {
154    pub title: *const c_char,
155    pub width: c_int,
156    pub height: c_int,
157    pub clear_color: affineui_color,
158    pub high_dpi: c_int,
159    pub vsync: c_int,
160    pub default_font_family: *const c_char,
161    pub default_font_size: c_int,
162    pub asset_folders: *const *const c_char,
163    pub asset_folder_count: usize,
164    pub perf_overlay: c_int,
165}
166
167// ── Embedded-mode structs (c_api.h) ──────────────────────────────────
168
169#[repr(C)]
170#[derive(Clone, Copy, Debug)]
171pub struct affineui_gpu_context {
172    pub backend: c_int,
173    pub d3d11_device: *const c_void,
174    pub d3d11_device_context: *const c_void,
175    pub metal_device: *const c_void,
176    pub wgpu_device: *const c_void,
177    pub color_format: c_int,
178    pub depth_format: c_int,
179    pub sample_count: c_int,
180}
181
182#[repr(C)]
183#[derive(Clone, Copy)]
184pub struct affineui_allocator {
185    pub alloc: Option<unsafe extern "C" fn(size: usize, align: usize, user: *mut c_void) -> *mut c_void>,
186    pub realloc: Option<
187        unsafe extern "C" fn(p: *mut c_void, old_sz: usize, new_sz: usize, align: usize, user: *mut c_void) -> *mut c_void,
188    >,
189    pub free: Option<unsafe extern "C" fn(p: *mut c_void, user: *mut c_void)>,
190    pub user: *mut c_void,
191}
192
193pub type affineui_log_fn = Option<unsafe extern "C" fn(level: c_int, msg: *const c_char, user: *mut c_void)>;
194
195#[repr(C)]
196#[derive(Clone, Copy)]
197pub struct affineui_init_desc {
198    pub gpu: *const affineui_gpu_context,
199    pub allocator: *const affineui_allocator,
200    pub log: affineui_log_fn,
201    pub log_user: *mut c_void,
202    pub default_font_family: *const c_char,
203    pub default_font_size: c_int,
204}
205
206#[repr(C)]
207#[derive(Clone, Copy, Debug)]
208pub struct affineui_frame_target {
209    pub width: c_int,
210    pub height: c_int,
211    pub dpi_scale: c_float,
212    pub sample_count: c_int,
213    pub clear: c_int,
214    pub viewport_x: c_int,
215    pub viewport_y: c_int,
216    pub viewport_w: c_int,
217    pub viewport_h: c_int,
218    pub d3d11_render_view: *const c_void,
219    pub d3d11_resolve_view: *const c_void,
220    pub d3d11_depth_stencil_view: *const c_void,
221    pub metal_current_drawable: *const c_void,
222    pub metal_depth_stencil_texture: *const c_void,
223    pub metal_msaa_color_texture: *const c_void,
224    pub wgpu_render_view: *const c_void,
225    pub wgpu_resolve_view: *const c_void,
226    pub wgpu_depth_stencil_view: *const c_void,
227    pub gl_framebuffer: u32,
228}
229
230// ── Callback shapes ──────────────────────────────────────────────────
231
232pub type affineui_user_free_fn = Option<unsafe extern "C" fn(user: *mut c_void)>;
233pub type affineui_ui_click_fn = Option<unsafe extern "C" fn(user: *mut c_void)>;
234pub type affineui_click_fn = Option<unsafe extern "C" fn(user: *mut c_void)>;
235pub type affineui_change_fn = Option<unsafe extern "C" fn(user: *mut c_void, value: *const c_char)>;
236pub type affineui_build_fn = Option<unsafe extern "C" fn(user: *mut c_void, view: *mut affineui_view)>;
237
238// ── Functions ────────────────────────────────────────────────────────
239
240extern "C" {
241    // Misc.
242    pub fn affineui_c_abi_version() -> c_int;
243    pub fn affineui_version() -> *const c_char;
244    pub fn affineui_run_html(html: *const c_char) -> c_int;
245    pub fn affineui_string_free(s: *mut c_char);
246
247    // Embedded-mode Ui.
248    pub fn affineui_ui_create() -> *mut affineui_ui;
249    pub fn affineui_ui_destroy(ui: *mut affineui_ui);
250    pub fn affineui_ui_init(ui: *mut affineui_ui, desc: *const affineui_init_desc);
251    pub fn affineui_ui_set_html(ui: *mut affineui_ui, html: *const c_char);
252    pub fn affineui_ui_set_css(ui: *mut affineui_ui, css: *const c_char);
253    pub fn affineui_ui_load_file(ui: *mut affineui_ui, path: *const c_char) -> c_int;
254    pub fn affineui_ui_set_clear_color(ui: *mut affineui_ui, r: u8, g: u8, b: u8, a: u8);
255    pub fn affineui_ui_render(ui: *mut affineui_ui, target: *const affineui_frame_target);
256    pub fn affineui_ui_dispatch(ui: *mut affineui_ui, ev: *const affineui_event) -> c_int;
257    pub fn affineui_ui_on_click(
258        ui: *mut affineui_ui,
259        selector: *const c_char,
260        fn_: affineui_ui_click_fn,
261        user: *mut c_void,
262        user_free: affineui_user_free_fn,
263    );
264    pub fn affineui_ui_hovered_cursor(ui: *const affineui_ui) -> c_int;
265    pub fn affineui_ui_set_attr(
266        ui: *mut affineui_ui,
267        elem_id: *const c_char,
268        name: *const c_char,
269        value: *const c_char,
270    ) -> c_int;
271    pub fn affineui_ui_remove_attr(ui: *mut affineui_ui, elem_id: *const c_char, name: *const c_char) -> c_int;
272    pub fn affineui_ui_set_text(ui: *mut affineui_ui, elem_id: *const c_char, text: *const c_char) -> c_int;
273    pub fn affineui_ui_content_size(ui: *const affineui_ui, out_w: *mut c_int, out_h: *mut c_int);
274    pub fn affineui_ui_needs_update(ui: *const affineui_ui) -> c_int;
275    pub fn affineui_ui_mark_dirty(ui: *mut affineui_ui);
276    pub fn affineui_ui_reset(ui: *mut affineui_ui);
277
278    // App.
279    pub fn affineui_app_config_init(cfg: *mut affineui_app_config);
280    pub fn affineui_app_create(cfg: *const affineui_app_config) -> *mut affineui_app;
281    pub fn affineui_app_destroy(app: *mut affineui_app);
282    pub fn affineui_app_load_html(app: *mut affineui_app, html: *const c_char);
283    pub fn affineui_app_load_html_file(app: *mut affineui_app, path: *const c_char) -> c_int;
284    pub fn affineui_app_load_view(app: *mut affineui_app, view: *const affineui_view);
285    pub fn affineui_app_set_stylesheet(app: *mut affineui_app, css: *const c_char, base_url: *const c_char);
286    pub fn affineui_app_invalidate(app: *mut affineui_app);
287    pub fn affineui_app_set_perf_overlay_enabled(app: *mut affineui_app, enabled: c_int);
288    pub fn affineui_app_perf_overlay_enabled(app: *const affineui_app) -> c_int;
289    pub fn affineui_app_dispatch(app: *mut affineui_app, ev: *const affineui_event) -> c_int;
290    pub fn affineui_app_run(app: *mut affineui_app) -> c_int;
291    pub fn affineui_app_quit(app: *mut affineui_app, code: c_int);
292    pub fn affineui_app_window_size(app: *const affineui_app, out_w: *mut c_int, out_h: *mut c_int);
293    pub fn affineui_app_framebuffer_size(app: *const affineui_app, out_w: *mut c_int, out_h: *mut c_int);
294    pub fn affineui_app_dpi_scale(app: *const affineui_app) -> c_float;
295    pub fn affineui_app_document(app: *mut affineui_app) -> *mut affineui_document;
296
297    // Document.
298    pub fn affineui_document_create() -> *mut affineui_document;
299    pub fn affineui_document_destroy(doc: *mut affineui_document);
300    pub fn affineui_document_set_html(doc: *mut affineui_document, html: *const c_char);
301    pub fn affineui_document_set_user_stylesheet(
302        doc: *mut affineui_document,
303        css: *const c_char,
304        base_url: *const c_char,
305    );
306    pub fn affineui_document_reload_stylesheets(doc: *mut affineui_document);
307    pub fn affineui_document_layout(doc: *mut affineui_document, viewport_width: c_int, viewport_height: c_int);
308    pub fn affineui_document_content_size(doc: *const affineui_document, out_w: *mut c_int, out_h: *mut c_int);
309    pub fn affineui_document_set_attribute_by_id(
310        doc: *mut affineui_document,
311        elem_id: *const c_char,
312        name: *const c_char,
313        value: *const c_char,
314    ) -> c_int;
315    pub fn affineui_document_remove_attribute_by_id(
316        doc: *mut affineui_document,
317        elem_id: *const c_char,
318        name: *const c_char,
319    ) -> c_int;
320    pub fn affineui_document_set_text_by_id(
321        doc: *mut affineui_document,
322        elem_id: *const c_char,
323        text: *const c_char,
324    ) -> c_int;
325    pub fn affineui_document_dispatch(
326        doc: *mut affineui_document,
327        ev: *const affineui_event,
328        out: *mut affineui_dispatch_result,
329    );
330    pub fn affineui_document_attach_script(doc: *mut affineui_document, script: c_int);
331    pub fn affineui_document_detach_script(doc: *mut affineui_document, script: c_int);
332    pub fn affineui_document_hovered_cursor(doc: *const affineui_document) -> c_int;
333
334    // View.
335    pub fn affineui_view_create(theme: c_int) -> *mut affineui_view;
336    pub fn affineui_view_destroy(view: *mut affineui_view);
337    pub fn affineui_view_clear(view: *mut affineui_view);
338    pub fn affineui_view_begin(view: *mut affineui_view);
339    pub fn affineui_view_end(view: *mut affineui_view);
340    pub fn affineui_view_set_theme(view: *mut affineui_view, theme: c_int);
341    pub fn affineui_view_get_theme(view: *const affineui_view) -> c_int;
342    pub fn affineui_view_set_framework_version(view: *mut affineui_view, version: *const c_char);
343    pub fn affineui_view_selector(view: *mut affineui_view, name: *const c_char, value: *const c_char);
344    pub fn affineui_view_to_html_fragment(view: *const affineui_view) -> *mut c_char;
345    pub fn affineui_view_to_html_document(view: *const affineui_view) -> *mut c_char;
346
347    pub fn affineui_view_heading(
348        view: *mut affineui_view,
349        level: c_int,
350        text: *const c_char,
351        classes: *const c_char,
352        key: *const c_char,
353    ) -> *mut affineui_widget;
354    pub fn affineui_view_paragraph(
355        view: *mut affineui_view,
356        text: *const c_char,
357        classes: *const c_char,
358        key: *const c_char,
359    ) -> *mut affineui_widget;
360    pub fn affineui_view_text(view: *mut affineui_view, text: *const c_char, key: *const c_char)
361        -> *mut affineui_widget;
362    pub fn affineui_view_html(view: *mut affineui_view, markup: *const c_char, key: *const c_char)
363        -> *mut affineui_widget;
364    pub fn affineui_view_button(
365        view: *mut affineui_view,
366        label: *const c_char,
367        primary: c_int,
368        key: *const c_char,
369    ) -> *mut affineui_widget;
370    pub fn affineui_view_checkbox(
371        view: *mut affineui_view,
372        label: *const c_char,
373        checked: c_int,
374        key: *const c_char,
375    ) -> *mut affineui_widget;
376    pub fn affineui_view_toggle(
377        view: *mut affineui_view,
378        label: *const c_char,
379        on: c_int,
380        key: *const c_char,
381    ) -> *mut affineui_widget;
382    pub fn affineui_view_input(
383        view: *mut affineui_view,
384        label: *const c_char,
385        value: *const c_char,
386        r#type: *const c_char,
387        key: *const c_char,
388    ) -> *mut affineui_widget;
389    pub fn affineui_view_password(
390        view: *mut affineui_view,
391        label: *const c_char,
392        value: *const c_char,
393        key: *const c_char,
394    ) -> *mut affineui_widget;
395    pub fn affineui_view_textarea(
396        view: *mut affineui_view,
397        label: *const c_char,
398        value: *const c_char,
399        rows: c_int,
400        key: *const c_char,
401    ) -> *mut affineui_widget;
402    pub fn affineui_view_dropdown(
403        view: *mut affineui_view,
404        label: *const c_char,
405        options: *const *const c_char,
406        option_count: usize,
407        selected: *const c_char,
408        key: *const c_char,
409    ) -> *mut affineui_widget;
410    pub fn affineui_view_button_group(
411        view: *mut affineui_view,
412        label: *const c_char,
413        options: *const *const c_char,
414        option_count: usize,
415        selected: *const c_char,
416        key: *const c_char,
417    ) -> *mut affineui_widget;
418    pub fn affineui_view_slider(
419        view: *mut affineui_view,
420        label: *const c_char,
421        value: f64,
422        min: f64,
423        max: f64,
424        key: *const c_char,
425    ) -> *mut affineui_widget;
426    pub fn affineui_view_knob(
427        view: *mut affineui_view,
428        label: *const c_char,
429        value: f64,
430        min: f64,
431        max: f64,
432        bipolar: c_int,
433        key: *const c_char,
434    ) -> *mut affineui_widget;
435    pub fn affineui_view_combo(
436        view: *mut affineui_view,
437        label: *const c_char,
438        value: f64,
439        step: f64,
440        key: *const c_char,
441    ) -> *mut affineui_widget;
442    pub fn affineui_view_color_field(
443        view: *mut affineui_view,
444        label: *const c_char,
445        value: *const c_char,
446        swatches: *const *const c_char,
447        swatch_count: usize,
448        key: *const c_char,
449    ) -> *mut affineui_widget;
450    pub fn affineui_view_colorfield(
451        view: *mut affineui_view,
452        label: *const c_char,
453        value: *const c_char,
454        key: *const c_char,
455    ) -> *mut affineui_widget;
456
457    pub fn affineui_view_container(
458        view: *mut affineui_view,
459        classes: *const c_char,
460        key: *const c_char,
461        build: affineui_build_fn,
462        user: *mut c_void,
463    ) -> *mut affineui_widget;
464    pub fn affineui_view_element(
465        view: *mut affineui_view,
466        tag: *const c_char,
467        classes: *const c_char,
468        key: *const c_char,
469        build: affineui_build_fn,
470        user: *mut c_void,
471    ) -> *mut affineui_widget;
472    pub fn affineui_view_panel(
473        view: *mut affineui_view,
474        key: *const c_char,
475        build: affineui_build_fn,
476        user: *mut c_void,
477    ) -> *mut affineui_widget;
478    pub fn affineui_view_card(
479        view: *mut affineui_view,
480        title: *const c_char,
481        classes: *const c_char,
482        key: *const c_char,
483        build: affineui_build_fn,
484        user: *mut c_void,
485    ) -> *mut affineui_widget;
486    pub fn affineui_view_toolbar(
487        view: *mut affineui_view,
488        key: *const c_char,
489        build: affineui_build_fn,
490        user: *mut c_void,
491    ) -> *mut affineui_widget;
492    pub fn affineui_view_menu_bar(
493        view: *mut affineui_view,
494        key: *const c_char,
495        build: affineui_build_fn,
496        user: *mut c_void,
497    ) -> *mut affineui_widget;
498    pub fn affineui_view_status_bar(
499        view: *mut affineui_view,
500        key: *const c_char,
501        build: affineui_build_fn,
502        user: *mut c_void,
503    ) -> *mut affineui_widget;
504    pub fn affineui_view_tree(
505        view: *mut affineui_view,
506        key: *const c_char,
507        build: affineui_build_fn,
508        user: *mut c_void,
509    ) -> *mut affineui_widget;
510    pub fn affineui_view_foldout(
511        view: *mut affineui_view,
512        title: *const c_char,
513        expanded: c_int,
514        key: *const c_char,
515        build: affineui_build_fn,
516        user: *mut c_void,
517    ) -> *mut affineui_widget;
518
519    pub fn affineui_view_toolbar_separator(view: *mut affineui_view, key: *const c_char) -> *mut affineui_widget;
520    pub fn affineui_view_icon_button(
521        view: *mut affineui_view,
522        icon: *const c_char,
523        key: *const c_char,
524    ) -> *mut affineui_widget;
525    pub fn affineui_view_menu_button(
526        view: *mut affineui_view,
527        label: *const c_char,
528        build: affineui_build_fn,
529        user: *mut c_void,
530        key: *const c_char,
531    ) -> *mut affineui_widget;
532    pub fn affineui_view_menu_item(
533        view: *mut affineui_view,
534        label: *const c_char,
535        icon: *const c_char,
536        shortcut: *const c_char,
537        key: *const c_char,
538    ) -> *mut affineui_widget;
539    pub fn affineui_view_menu_separator(view: *mut affineui_view, key: *const c_char) -> *mut affineui_widget;
540    pub fn affineui_view_submenu(
541        view: *mut affineui_view,
542        label: *const c_char,
543        build: affineui_build_fn,
544        user: *mut c_void,
545        icon: *const c_char,
546        key: *const c_char,
547    ) -> *mut affineui_widget;
548    pub fn affineui_view_menu_brand(
549        view: *mut affineui_view,
550        title: *const c_char,
551        icon: *const c_char,
552        key: *const c_char,
553    ) -> *mut affineui_widget;
554    pub fn affineui_view_menu_spacer(view: *mut affineui_view, key: *const c_char) -> *mut affineui_widget;
555    pub fn affineui_view_menu_meta(
556        view: *mut affineui_view,
557        text: *const c_char,
558        key: *const c_char,
559    ) -> *mut affineui_widget;
560    pub fn affineui_view_tree_row(
561        view: *mut affineui_view,
562        label: *const c_char,
563        selected: c_int,
564        depth: c_int,
565        key: *const c_char,
566    ) -> *mut affineui_widget;
567    pub fn affineui_view_splitter(
568        view: *mut affineui_view,
569        horizontal: c_int,
570        key: *const c_char,
571    ) -> *mut affineui_widget;
572    pub fn affineui_view_find_widget(view: *mut affineui_view, name: *const c_char) -> *mut affineui_widget;
573
574    // Widget.
575    pub fn affineui_widget_destroy(w: *mut affineui_widget);
576    pub fn affineui_widget_valid(w: *const affineui_widget) -> c_int;
577    pub fn affineui_widget_get_kind(w: *const affineui_widget) -> c_int;
578    pub fn affineui_widget_name(w: *const affineui_widget) -> *mut c_char;
579    pub fn affineui_widget_attr(
580        w: *const affineui_widget,
581        name: *const c_char,
582        fallback: *const c_char,
583    ) -> *mut c_char;
584    pub fn affineui_widget_text(w: *const affineui_widget) -> *mut c_char;
585    pub fn affineui_widget_has_attr(w: *const affineui_widget, name: *const c_char) -> c_int;
586    pub fn affineui_widget_set_text(w: *mut affineui_widget, text: *const c_char);
587    pub fn affineui_widget_set_attr(w: *mut affineui_widget, name: *const c_char, value: *const c_char);
588    pub fn affineui_widget_remove_attr(w: *mut affineui_widget, name: *const c_char);
589    pub fn affineui_widget_set_selector(w: *mut affineui_widget, name: *const c_char, value: *const c_char);
590    pub fn affineui_widget_add_class(w: *mut affineui_widget, classes: *const c_char);
591    pub fn affineui_widget_clear(w: *mut affineui_widget);
592    pub fn affineui_widget_on_click(
593        w: *mut affineui_widget,
594        fn_: affineui_click_fn,
595        user: *mut c_void,
596        user_free: affineui_user_free_fn,
597    );
598    pub fn affineui_widget_on_change(
599        w: *mut affineui_widget,
600        fn_: affineui_change_fn,
601        user: *mut c_void,
602        user_free: affineui_user_free_fn,
603    );
604    pub fn affineui_widget_append(w: *mut affineui_widget, build: affineui_build_fn, user: *mut c_void);
605    pub fn affineui_widget_replace(w: *mut affineui_widget, build: affineui_build_fn, user: *mut c_void);
606    pub fn affineui_widget_find_widget(w: *const affineui_widget, name: *const c_char) -> *mut affineui_widget;
607}