1#[derive(Clone, Copy, Debug, PartialEq, Eq)]
23pub enum Cell {
24 Is(&'static str),
29 As(&'static str),
33 No(&'static str),
35}
36
37pub struct Door {
39 pub rust: &'static str,
43 pub c: Cell,
44 pub node: Cell,
45 pub lua: Cell,
46 pub doc: &'static str,
47}
48
49use Cell::{As, Is, No};
50
51pub const GUEST: &str = "a script is a guest in the host's frame (ADR 0014): its env is the view's reading, and registering, driving, pacing and reading back are the host's";
56
57const NO_HANDLE: &str = "a script owns no handle: the host registers and the script names the id it was given (`image { id = }`, `font = id`, `audio { src = id }`)";
59
60const NEVER_PAINTS: &str = "a Node host never paints: the renderer behind `KuiWindow` is the runner's, and a headless `Ctx` has none";
63
64pub const DOORS: &[Door] = &[
65 Door {
67 rust: "SharedResources::add_image",
68 c: Is("kui_image_add"),
69 node: Is("addImage"),
70 lua: No(NO_HANDLE),
71 doc: "Registers RGBA pixels and mints an id for `<image src>`.",
72 },
73 Door {
74 rust: "Core::update_image",
75 c: Is("kui_image_update"),
76 node: Is("updateImage"),
77 lua: No(NO_HANDLE),
78 doc: "Replaces the pixels behind a live id, keeping the id (ADR 0025).",
79 },
80 Door {
81 rust: "Core::remove_image",
82 c: Is("kui_image_remove"),
83 node: Is("removeImage"),
84 lua: No(NO_HANDLE),
85 doc: "Drops an image; every window's atlas lets it go (backlog AR8).",
86 },
87 Door {
88 rust: "Core::image_pixels",
89 c: Is("kui_image_pixels"),
90 node: No(NEVER_PAINTS),
91 lua: No(NO_HANDLE),
92 doc: "The pixels behind a handle, for a renderer meeting a texture quad.",
93 },
94 Door {
95 rust: "Core::parse_path",
96 c: Is("kui_path_parse"),
97 node: As("`d` on `<path>` is the string; the addon hands it to this parser"),
98 lua: As("`d` on `path { }` is the string; the host hands it to this parser"),
99 doc: "SVG path data to the flat op form a `path` draws (ADR 0040): one parser, so every binding draws the same shape.",
100 },
101 Door {
102 rust: "Core::add_fragment",
103 c: Is("kui_fragment_add"),
104 node: Is("addFragment"),
105 lua: No(NO_HANDLE),
106 doc: "Registers a WGSL function and mints an id for `<fragment src>` (ADR 0015).",
107 },
108 Door {
109 rust: "Core::remove_fragment",
110 c: Is("kui_fragment_remove"),
111 node: Is("removeFragment"),
112 lua: No(NO_HANDLE),
113 doc: "Drops a fragment; the renderer drops its pipelines (backlog AR8).",
114 },
115 Door {
116 rust: "Core::fragment_module_source",
117 c: Is("kui_fragment_source"),
118 node: No(NEVER_PAINTS),
119 lua: No(NO_HANDLE),
120 doc: "The whole WGSL module behind a handle, which is what a renderer compiles.",
121 },
122 Door {
123 rust: "Core::add_font_data",
124 c: Is("kui_font_add"),
125 node: Is("addFont"),
126 lua: No(NO_HANDLE),
127 doc: "Registers a font's bytes and mints an id for `font`.",
128 },
129 Door {
130 rust: "Core::add_system_font",
131 c: Is("kui_font_add_system"),
132 node: Is("addSystemFont"),
133 lua: No(NO_HANDLE),
134 doc: "Registers an installed family by name.",
135 },
136 Door {
137 rust: "Core::load_font_file",
138 c: Is("kui_font_load_file"),
139 node: Is("loadFontFile"),
140 lua: No(NO_HANDLE),
141 doc: "Registers a font file by path.",
142 },
143 Door {
144 rust: "Core::load_fonts_dir",
145 c: Is("kui_font_load_dir"),
146 node: Is("loadFontsDir"),
147 lua: No(NO_HANDLE),
148 doc: "Registers every font file in a directory.",
149 },
150 Door {
151 rust: "Core::reload_system_fonts",
152 c: Is("kui_font_reload_system"),
153 node: Is("reloadSystemFonts"),
154 lua: No(GUEST),
155 doc: "Scans the system's fonts again, so a font installed while the app runs is found (the scan is otherwise once a process); returns how many faces came and went.",
156 },
157 Door {
158 rust: "Core::set_fallback_fonts",
159 c: Is("kui_font_set_fallback"),
160 node: Is("setFallbackFonts"),
161 lua: No(NO_HANDLE),
162 doc: "The fonts asked, in order, for a character the text's own family lacks, before the platform's fallback list (backlog F121).",
163 },
164 Door {
165 rust: "Core::fallback_fonts",
166 c: No("the list is the one the host set"),
167 node: No("the list is the one the host set"),
168 lua: No(NO_HANDLE),
169 doc: "The families `set_fallback_fonts` named, in order.",
170 },
171 Door {
172 rust: "Core::remove_font",
173 c: Is("kui_font_remove"),
174 node: Is("removeFont"),
175 lua: No(NO_HANDLE),
176 doc: "Drops a font.",
177 },
178 Door {
179 rust: "Core::system_font_families",
180 c: Is("kui_font_families"),
181 node: Is("systemFontFamilies"),
182 lua: No(NO_HANDLE),
183 doc: "The installed family names `add_system_font` accepts.",
184 },
185 Door {
186 rust: "Core::system_fonts",
187 c: Is("kui_system_fonts"),
188 node: Is("systemFonts"),
189 lua: No(NO_HANDLE),
190 doc: "The same families, each with what the font database read off its faces: `monospaced` (every face fixed-pitch), `weights`, `italic` (backlog F97) — a font picker's monospaced-first list without a file loaded or a glyph shaped.",
191 },
192 Door {
193 rust: "Core::add_sound",
194 c: Is("kui_sound_add"),
195 node: Is("addSound"),
196 lua: No(NO_HANDLE),
197 doc: "Registers a sound's bytes and mints an id for `<audio src>`, `clickSound` and `play`.",
198 },
199 Door {
200 rust: "Core::remove_sound",
201 c: Is("kui_sound_remove"),
202 node: Is("removeSound"),
203 lua: No(NO_HANDLE),
204 doc: "Drops a sound.",
205 },
206 Door {
207 rust: "Core::set_text_cache_budget",
208 c: Is("kui_set_text_cache_budget"),
209 node: Is("setTextCacheBudget"),
210 lua: No(GUEST),
211 doc: "The shaped-text cache's byte budget (backlog C16).",
212 },
213 Door {
214 rust: "Core::text_cache_bytes",
215 c: Is("kui_text_cache_bytes"),
216 node: Is("textCacheBytes"),
217 lua: No(GUEST),
218 doc: "What the shaped-text cache holds.",
219 },
220 Door {
222 rust: "Ui::play",
223 c: Is("kui_play"),
224 node: Is("play"),
225 lua: No(
226 "a script owns no sound handle, and its env is the view's: a playback started there would start again every frame — `audio { src = id }` is the declarative form, and what a script has",
227 ),
228 doc: "Starts a playback of a registered sound, outside any node; answers the playback id.",
229 },
230 Door {
231 rust: "Core::stop",
232 c: Is("kui_stop"),
233 node: Is("stop"),
234 lua: No("as `play`: a script declares `audio { }` and stops it by not declaring it"),
235 doc: "Stops a playback, with an optional fade.",
236 },
237 Door {
238 rust: "Core::set_volume",
239 c: Is("kui_set_volume"),
240 node: Is("setVolume"),
241 lua: As("`audio { volume = }` applies live"),
242 doc: "A playback's volume, with an optional tween.",
243 },
244 Door {
245 rust: "Core::pause",
246 c: Is("kui_pause"),
247 node: Is("pause"),
248 lua: As("`audio { paused = true }` applies live"),
249 doc: "Pauses a playback.",
250 },
251 Door {
252 rust: "Core::resume",
253 c: Is("kui_resume"),
254 node: Is("resume"),
255 lua: As("`audio { paused = false }`"),
256 doc: "Resumes a paused playback.",
257 },
258 Door {
259 rust: "Core::set_master_volume",
260 c: Is("kui_set_master_volume"),
261 node: Is("setMasterVolume"),
262 lua: No(GUEST),
263 doc: "The device's master volume, with an optional tween.",
264 },
265 Door {
267 rust: "Ui::announce",
268 c: Is("kui_announce"),
269 node: Is("announce"),
270 lua: Is("announce"),
271 doc: "Says something once with no node behind it (ADR 0001).",
272 },
273 Door {
274 rust: "Core::take_announcements",
275 c: Is("kui_take_announcements"),
276 node: Is("Ctx.announcements"),
277 lua: No(GUEST),
278 doc: "Drains what was announced, for a host bridging assistive technology; a `KuiWindow`'s bridge is the runner's.",
279 },
280 Door {
281 rust: "Core::access_tree",
282 c: Is("kui_access_tree"),
283 node: Is("accessTree"),
284 lua: No(GUEST),
285 doc: "The access tree of the last finished frame (ADR 0001).",
286 },
287 Door {
289 rust: "Ui::focus",
290 c: Is("kui_focus"),
291 node: Is("focus"),
292 lua: Is("set_focus"),
293 doc: "Moves focus to a node now; an app's move stands over a modal's restore (backlog AR17). `keyFocus` is the declarative, edge-triggered form.",
294 },
295 Door {
296 rust: "Ui::blur",
297 c: As("`kui_focus(ctx, 0)`"),
298 node: Is("blur"),
299 lua: Is("blur"),
300 doc: "Drops focus.",
301 },
302 Door {
303 rust: "Ui::focus_next",
304 c: Is("kui_focus_next"),
305 node: Is("focusNext"),
306 lua: Is("focus_next"),
307 doc: "Steps the Tab ring forward (ADR 0002).",
308 },
309 Door {
310 rust: "Ui::focus_prev",
311 c: As("`kui_focus_next(ctx, false)`"),
312 node: Is("focusPrev"),
313 lua: Is("focus_prev"),
314 doc: "Steps the Tab ring backward.",
315 },
316 Door {
317 rust: "Ui::focus_region",
318 c: Is("kui_focus_region"),
319 node: Is("focusRegion"),
320 lua: Is("focus_region"),
321 doc: "Enters a `focusRegion`'s ring, or leaves it for the main one (ADR 0022).",
322 },
323 Door {
324 rust: "Ui::region",
325 c: Is("kui_region"),
326 node: Is("region"),
327 lua: As("`env.region`, a reading"),
328 doc: "The region in effect.",
329 },
330 Door {
331 rust: "Ui::focused",
332 c: Is("kui_focused"),
333 node: Is("focused"),
334 lua: As("`env.focus`, a reading"),
335 doc: "The focused node's key.",
336 },
337 Door {
338 rust: "Ui::is_focused",
339 c: Is("kui_is_focused"),
340 node: Is("isFocused"),
341 lua: Is("is_focused"),
342 doc: "Whether a node has focus.",
343 },
344 Door {
345 rust: "Ui::focus_visible",
346 c: Is("kui_focus_visible"),
347 node: Is("focusVisible"),
348 lua: As("`env.focus_visible`, a reading"),
349 doc: "Whether focus came from the keyboard and the ring should show.",
350 },
351 Door {
352 rust: "Ui::key_of",
353 c: Is("kui_key_of"),
354 node: Is("keyOf"),
355 lua: As("every query and verb takes the label itself (`key_query`)"),
356 doc: "The key a label names this frame.",
357 },
358 Door {
359 rust: "Core::label_of",
360 c: No(
361 "the label is the app's own word for the node, and every door names a node by it or by the key an event carried; the one reader is the devtools' inspector, in the core",
362 ),
363 node: No("the same reason as C's"),
364 lua: No("the same reason as C's"),
365 doc: "The label a key was opened under.",
366 },
367 Door {
368 rust: "Ui::caret_visible",
369 c: Is("kui_caret_visible"),
370 node: Is("caretVisible"),
371 lua: As("`env.caret_visible`, a reading"),
372 doc: "The blink phase a custom editor draws its caret on.",
373 },
374 Door {
375 rust: "Core::set_caret_visible",
376 c: Is("kui_set_caret_visible"),
377 node: Is("setCaretVisible"),
378 lua: No(GUEST),
379 doc: "The host's blink clock writes the phase.",
380 },
381 Door {
382 rust: "Core::has_caret",
383 c: Is("kui_has_caret"),
384 node: Is("hasCaret"),
385 lua: No(GUEST),
386 doc: "Whether anything focused draws a caret to blink — a `caretSolid` line's is not one — which arms a host's blink clock.",
387 },
388 Door {
389 rust: "Core::caret_stamp",
390 c: Is("kui_caret_stamp"),
391 node: As(
392 "the loop in `index.js` runs the blink from `nextDeadlineMs`; a headless `Ctx` never blinks",
393 ),
394 lua: No(GUEST),
395 doc: "Changes when the caret moves or focus does, which re-arms the clock solid.",
396 },
397 Door {
399 rust: "Ui::is_hovered",
400 c: Is("kui_is_hovered"),
401 node: Is("isHovered"),
402 lua: Is("is_hovered"),
403 doc: "Whether the pointer is over a node.",
404 },
405 Door {
406 rust: "Ui::is_pressed",
407 c: Is("kui_is_pressed"),
408 node: Is("isPressed"),
409 lua: Is("is_pressed"),
410 doc: "Whether a press started on a node and the pointer is still over it.",
411 },
412 Door {
413 rust: "Ui::is_drop_target",
414 c: Is("kui_is_drop_target"),
415 node: Is("isDropTarget"),
416 lua: Is("is_drop_target"),
417 doc: "Whether files dragged in from the OS are over a node (ADR 0031) — for drop-dependent layout; the colour is `drop_bg`.",
418 },
419 Door {
420 rust: "Core::drop_target",
421 c: Is("kui_drop_target"),
422 node: Is("dropTarget"),
423 lua: Is("drop_target"),
424 doc: "The drop zone the dragged files are over, if any — what a driver answers the OS with, and what a test reads to say a zone was found (ADR 0031, decision 5).",
425 },
426 Door {
427 rust: "Ui::is_group_hovered",
428 c: As(
429 "`hoverBg` / `pressedBg` on a `hoverGroup` member paint it; the reader is what the Rust widgets ask when they paint by hand",
430 ),
431 node: As("the same form as C's"),
432 lua: As("the same form as C's"),
433 doc: "Whether any member of a hover group is hovered (`is_group_pressed` the same for a press).",
434 },
435 Door {
436 rust: "Core::cursor",
437 c: No("the pointer's position is the driver's own fact — it injected it"),
438 node: No("the same reason as C's"),
439 lua: No("the same reason as C's, one step removed"),
440 doc: "Where the pointer is, in logical viewport px.",
441 },
442 Door {
443 rust: "Core::cursor_shape",
444 c: Is("kui_cursor_shape"),
445 node: Is("cursorShape"),
446 lua: No(GUEST),
447 doc: "The pointer shape the frame asks for, which the host sets on its window.",
448 },
449 Door {
450 rust: "Ui::layout_of",
451 c: Is("kui_layout_of"),
452 node: Is("layoutOf"),
453 lua: Is("layout_of"),
454 doc: "Where layout put a node last frame (backlog C26).",
455 },
456 Door {
457 rust: "Ui::scroll_offset",
458 c: Is("kui_scroll_offset"),
459 node: Is("scrollOffset"),
460 lua: Is("scroll_offset"),
461 doc: "A scrolling node's offset.",
462 },
463 Door {
464 rust: "Ui::scroll_geometry",
465 c: Is("kui_scroll_geometry"),
466 node: Is("scrollGeometry"),
467 lua: Is("scroll_geometry"),
468 doc: "A scrolling node's viewport and content sizes.",
469 },
470 Door {
471 rust: "Ui::set_scroll",
472 c: Is("kui_set_scroll"),
473 node: Is("setScroll"),
474 lua: Is("set_scroll"),
475 doc: "Scrolls a node to an offset.",
476 },
477 Door {
478 rust: "Ui::shift_scroll",
479 c: Is("kui_shift_scroll"),
480 node: Is("shiftScroll"),
481 lua: Is("shift_scroll"),
482 doc: "Moves a node's scroll by content that moved under it, with no ease: a variable-height list's anchor (backlog C46).",
483 },
484 Door {
485 rust: "Ui::reveal",
486 c: Is("kui_reveal"),
487 node: Is("reveal"),
488 lua: Is("reveal"),
489 doc: "Scrolls whatever encloses a node until it is in view.",
490 },
491 Door {
492 rust: "Ui::text_hit",
493 c: Is("kui_text_hit"),
494 node: Is("textHit"),
495 lua: Is("text_hit"),
496 doc: "The byte and line under a point in a node's text (backlog C18).",
497 },
498 Door {
499 rust: "Ui::caret_rect",
500 c: Is("kui_caret_rect"),
501 node: Is("caretRect"),
502 lua: Is("caret_rect"),
503 doc: "The caret rect for a byte offset in a node's text.",
504 },
505 Door {
506 rust: "Core::ime_rect",
507 c: Is("kui_ime_rect"),
508 node: Is("imeRect"),
509 lua: No(GUEST),
510 doc: "Where the OS candidate window goes, which the host hands to the platform (backlog C17).",
511 },
512 Door {
513 rust: "Ui::measure_text",
514 c: Is("kui_measure_text"),
515 node: Is("measureText"),
516 lua: Is("measure_text"),
517 doc: "Shapes text in a style at a width and answers its size and line count.",
518 },
519 Door {
520 rust: "Ui::measure_rich_text",
521 c: Is("kui_measure_rich_text"),
522 node: As("`measureText` takes spans too"),
523 lua: As("`measure_text` takes spans too"),
524 doc: "The same for spans, shaped as one paragraph.",
525 },
526 Door {
527 rust: "Ui::edit_text",
528 c: Is("kui_edit_text"),
529 node: Is("editText"),
530 lua: Is("edit_text"),
531 doc: "An editor's text, by key or by label.",
532 },
533 Door {
534 rust: "Ui::set_edit_text",
535 c: Is("kui_edit_set_text"),
536 node: Is("setEditText"),
537 lua: Is("set_edit_text"),
538 doc: "Replaces an editor's text, caret at the end.",
539 },
540 Door {
541 rust: "Ui::set_edit_text_by_label",
542 c: Is("kui_edit_set_text_label"),
543 node: As("`setEditText` takes the label too"),
544 lua: As("`set_edit_text` takes the label too"),
545 doc: "The same by the label an editor's `key` declares, which reaches one the frame is about to declare (backlog AR26).",
546 },
547 Door {
548 rust: "Core::animating",
549 c: Is("kui_animating"),
550 node: Is("animating"),
551 lua: No(GUEST),
552 doc: "Whether the last frame left a transition mid-flight, so the host draws another without waiting for input.",
553 },
554 Door {
555 rust: "Core::owed",
556 c: Is("kui_owed"),
557 node: Is("owed"),
558 lua: No(GUEST),
559 doc: "The same by kind — a finite transition, a keyframe cycle, a departing ghost, a requested frame, an autoscroll — so a test can wait for the transitions to run out under a cycle that never ends; Node's loop has `quiet()` for that wait (backlog F64).",
560 },
561 Door {
562 rust: "Core::set_frame_trace",
563 c: Is("kui_set_frame_trace"),
564 node: Is("setFrameTrace"),
565 lua: No(GUEST),
566 doc: "Turns on the trace of why frames run: who holds an owed frame, and whether a frame changed what is drawn (backlog F111).",
567 },
568 Door {
569 rust: "Core::frame_cause",
570 c: Is("kui_frame_cause"),
571 node: Is("frameCause"),
572 lua: No(GUEST),
573 doc: "Why the frame being built runs: the input it answers by kind, what the driver noted, and `owed` after a frame that owed one (backlog F111).",
574 },
575 Door {
576 rust: "Core::begin_frame_cause",
577 c: No(
578 "a C host's view runs between `kui_frame_begin` and `kui_frame_finish`, inside the frame it builds, so it reads that frame already",
579 ),
580 node: Is("Ctx.beginFrameCause"),
581 lua: No(GUEST),
582 doc: "Starts the next frame's record ahead of its `begin_frame`, for a driver whose view runs before the frame it is for — Node's loop — so `frame_cause` and `owed_by` read from the view answer that frame (backlog RG81).",
583 },
584 Door {
585 rust: "Core::note_frame_cause",
586 c: Is("kui_note_frame_cause"),
587 node: No(
588 "the drivers that note a reason are kui-native's, which a `KuiWindow` runs on; a `Ctx` driven by hand has nothing but the input the core already records",
589 ),
590 lua: No(GUEST),
591 doc: "A driver adds a reason the core cannot see — a wake, a resize, a blink, a retry — to the next frame's (backlog F111).",
592 },
593 Door {
594 rust: "Core::owed_by",
595 c: No(
596 "lists of named holders are strings the library would own across calls, an [out-array] struct and an ABI bump for a reading that is a debugging aid; a C host reads the kinds from `kui_owed`",
597 ),
598 node: Is("owedBy"),
599 lua: No(GUEST),
600 doc: "Who holds the frame the last one left owed: `owed` with the nodes, slots and calling lines named (backlog F111).",
601 },
602 Door {
603 rust: "Core::frame_unchanged",
604 c: Is("kui_frame_unchanged"),
605 node: Is("frameUnchanged"),
606 lua: No(GUEST),
607 doc: "Whether the last finished frame drew exactly what the one before drew, traced (backlog F111).",
608 },
609 Door {
610 rust: "Ui::request_frame",
611 c: As("`animate` on a node, and `kui_animating` for the driver to read"),
612 node: As("the same form as C's"),
613 lua: As("the same form as C's"),
614 doc: "Asks for a frame after this one; the driver paces off `animating()`.",
615 },
616 Door {
617 rust: "Ui::modifiers",
618 c: No(
619 "the held modifiers ride on every key and pointer event's `mods`; the reader is what the stock editor's Shift-drag asks, inside the core",
620 ),
621 node: No("the same reason as C's"),
622 lua: No("the same reason as C's"),
623 doc: "The modifier keys held now.",
624 },
625 Door {
627 rust: "Ui::selection_text",
628 c: Is("kui_selection_text"),
629 node: Is("selectionText"),
630 lua: Is("selection_text"),
631 doc: "The window's selected text — a scope's, a grid's or the focused editor's.",
632 },
633 Door {
634 rust: "Ui::selection_html",
635 c: Is("kui_selection_html"),
636 node: Is("selectionHtml"),
637 lua: Is("selection_html"),
638 doc: "The same with the formatting the text declared.",
639 },
640 Door {
641 rust: "Ui::selection_ends",
642 c: Is("kui_selection_ends"),
643 node: Is("selectionEnds"),
644 lua: Is("selection_ends"),
645 doc: "A text selection's anchor and focus as row indices and bytes (ADR 0029).",
646 },
647 Door {
648 rust: "Ui::cell_selection",
649 c: Is("kui_cell_selection"),
650 node: Is("cellSelection"),
651 lua: Is("cell_selection"),
652 doc: "A `cells` grid's selection: its ends as absolute lines and columns, and whether it is a block (ADR 0017 §4).",
653 },
654 Door {
655 rust: "Ui::select_all_in",
656 c: Is("kui_select_all_in"),
657 node: Is("selectAllIn"),
658 lua: Is("select_all_in"),
659 doc: "Select All, scoped to a `selectable` node or a grid.",
660 },
661 Door {
662 rust: "Ui::clear_selection",
663 c: Is("kui_clear_selection"),
664 node: Is("clearSelection"),
665 lua: Is("clear_selection"),
666 doc: "Drops the window's selection.",
667 },
668 Door {
669 rust: "Ui::request_copy",
670 c: Is("kui_request_copy"),
671 node: Is("requestCopy"),
672 lua: Is("request_copy"),
673 doc: "Asks for the selection as a copy, which may come back as a `selectionrange` question.",
674 },
675 Door {
676 rust: "Ui::answer_selection_range",
677 c: Is("kui_answer_selection_range"),
678 node: Is("answerSelectionRange"),
679 lua: Is("answer_selection_range"),
680 doc: "The app's answer to that question.",
681 },
682 Door {
683 rust: "Ui::set_clipboard",
684 c: Is("kui_set_clipboard"),
685 node: Is("setClipboard"),
686 lua: Is("set_clipboard"),
687 doc: "A key sink's own Ctrl-C: posts a clipboard action for the host (backlog C33).",
688 },
689 Door {
690 rust: "Ui::set_clipboard_secret",
691 c: Is("kui_set_clipboard_secret"),
692 node: Is("setClipboardSecret"),
693 lua: Is("set_clipboard_secret"),
694 doc: "Posts a secret for the clipboard, which the host writes marked concealed and transient the way a password manager does, so no clipboard manager shows or keeps it (backlog F84).",
695 },
696 Door {
697 rust: "Ui::request_paste",
698 c: Is("kui_request_paste"),
699 node: Is("requestPaste"),
700 lua: Is("request_paste"),
701 doc: "A key sink's own Ctrl-V: the clipboard comes back as a commit, marked `concealed` / `transient` when the pasteboard said so (backlog F84). One ask at a time — a second while one is unanswered is dropped.",
702 },
703 Door {
704 rust: "Ui::awaiting_paste",
705 c: Is("kui_awaiting_paste"),
706 node: Is("awaitingPaste"),
707 lua: Is("awaiting_paste"),
708 doc: "Whether a paste asked for is still unanswered (backlog AR34).",
709 },
710 Door {
711 rust: "Ui::request_files",
712 c: Is("kui_request_files"),
713 node: Is("requestFiles"),
714 lua: Is("request_files"),
715 doc: "Asks for the platform's Open, Save or folder dialog; the answer is a `files` event to whoever asked. One at a time — a second while one is out is dropped (backlog C51).",
716 },
717 Door {
718 rust: "Ui::awaiting_files",
719 c: Is("kui_awaiting_files"),
720 node: Is("awaitingFiles"),
721 lua: Is("awaiting_files"),
722 doc: "Whether a file dialog asked for is still unanswered.",
723 },
724 Door {
725 rust: "Core::take_file_requests",
726 c: As("`kui_take_file_request`, then `kui_file_request_filter` per filter"),
727 node: Is("takeFileRequests"),
728 lua: No(GUEST),
729 doc: "Drains the dialog asked for, for a host that shows it itself; the runner does. The answer goes back as input (`Ctx.answerFiles`, `kui_input_files`).",
730 },
731 Door {
732 rust: "Core::set_lookup_available",
733 c: Is("kui_set_lookup_available"),
734 node: Is("setLookupAvailable"),
735 lua: No(GUEST),
736 doc: "Whether the host can show the platform's definition panel, which decides whether Look Up is offered.",
737 },
738 Door {
740 rust: "Ui::open_menu",
741 c: Is("kui_open_menu"),
742 node: Is("openMenu"),
743 lua: Is("open_menu"),
744 doc: "Opens a context menu on a node at a point.",
745 },
746 Door {
747 rust: "Ui::close_menu",
748 c: Is("kui_close_menu"),
749 node: Is("closeMenu"),
750 lua: Is("close_menu"),
751 doc: "Closes it.",
752 },
753 Door {
754 rust: "Core::take_menu_actions",
755 c: Is("kui_take_menu_action"),
756 node: Is("takeMenuActions"),
757 lua: As(
758 "a chosen row comes back as a `menu` event on the node; the clipboard actions are the host's",
759 ),
760 doc: "Drains what a menu (or a chord, or the standard bar) asked of the host: a clipboard write, a paste, a Look Up.",
761 },
762 Door {
763 rust: "Core::menu",
764 c: As("`kui_menu_item_count` / `kui_menu_item`, one row at a time"),
765 node: Is("menu"),
766 lua: No(GUEST),
767 doc: "The open menu, for a host showing it natively.",
768 },
769 Door {
770 rust: "Core::set_native_menus",
771 c: Is("kui_set_native_menus"),
772 node: Is("setNativeMenus"),
773 lua: No(GUEST),
774 doc: "Whether the host shows menus itself; the core then draws none.",
775 },
776 Door {
777 rust: "Core::activate_menu_item",
778 c: Is("kui_activate_menu_item"),
779 node: Is("activateMenuItem"),
780 lua: No(GUEST),
781 doc: "Reports that the host's own menu chose a row; a row that cannot be chosen (disabled, a separator) is refused and the menu stays open.",
782 },
783 Door {
784 rust: "Core::menu_bar",
785 c: As(
786 "`kui_menu_bar_menu_count` / `kui_menu_bar_menu` / `kui_menu_bar_item`, one row at a time",
787 ),
788 node: Is("menuBar"),
789 lua: No(GUEST),
790 doc: "The declared menu bar, for a host handing it to the OS.",
791 },
792 Door {
793 rust: "Core::set_native_menu_bar",
794 c: Is("kui_set_native_menu_bar"),
795 node: Is("setNativeMenuBar"),
796 lua: No(GUEST),
797 doc: "Whether the host owns the bar; the core then draws no strip.",
798 },
799 Door {
800 rust: "Core::activate_menu_bar_item",
801 c: Is("kui_activate_menu_bar_item"),
802 node: Is("activateMenuBarItem"),
803 lua: No(GUEST),
804 doc: "Reports that the OS bar chose a row.",
805 },
806 Door {
808 rust: "Ui::window",
809 c: Is("kui_window_declare"),
810 node: As("the root's `windows` prop"),
811 lua: As("the root's `windows` field"),
812 doc: "Declares that a named window exists this frame (ADR 0003 step 3).",
813 },
814 Door {
815 rust: "Core::windows",
816 c: As("the ids arrive on `KUI_CMD_OPEN`; a host keeps the list it opened"),
817 node: Is("windows"),
818 lua: No(GUEST),
819 doc: "The names of the windows open now.",
820 },
821 Door {
822 rust: "Ui::window_name",
823 c: Is("kui_ctx_window_name"),
824 node: Is("windowName"),
825 lua: As("`env.window.name`, a reading"),
826 doc: "The name of the window this context draws.",
827 },
828 Door {
829 rust: "Ui::set_window_size",
830 c: Is("kui_set_window_size"),
831 node: Is("setWindowSize"),
832 lua: Is("set_window_size"),
833 doc: "Asks the driver to resize a window.",
834 },
835 Door {
836 rust: "Ui::focus_window",
837 c: Is("kui_focus_window"),
838 node: Is("focusWindow"),
839 lua: Is("focus_window"),
840 doc: "Asks the driver to bring a window to the front.",
841 },
842 Door {
843 rust: "Ui::window_title",
844 c: Is("kui_window_title"),
845 node: As("the root's `title` prop"),
846 lua: As("the root's `title` field"),
847 doc: "Declares the window's title this frame.",
848 },
849 Door {
850 rust: "Ui::always_on_top",
851 c: Is("kui_set_always_on_top"),
852 node: As("the root's `alwaysOnTop` prop"),
853 lua: As("the root's `always_on_top` field"),
854 doc: "Declares that the window sits above every other app's this frame (backlog C30).",
855 },
856 Door {
857 rust: "Ui::secure_input",
858 c: Is("kui_set_secure_input"),
859 node: As("the root's `secureInput` prop"),
860 lua: As("the root's `secure_input` field"),
861 doc: "Declares that this frame wants secure keyboard entry while the window has the keyboard — a password prompt (backlog F85).",
862 },
863 Door {
864 rust: "Ui::option_as_alt",
865 c: Is("kui_set_option_as_alt"),
866 node: As("the root's `optionAsAlt` prop"),
867 lua: As("the root's `option_as_alt` field"),
868 doc: "Declares which Option keys act as Alt in this window on macOS, so a dead key like ⌥u arrives as `<A-u>` (backlog F113).",
869 },
870 Door {
871 rust: "Ui::window_command",
872 c: As(
873 "the chrome roles (`KuiSpec.window_role`) are the door; the verb is what `widgets::window_buttons` lowers to",
874 ),
875 node: As(
876 "`KuiWindow.close()` for the one command the runner takes from outside a frame; the rest are `windowRole`",
877 ),
878 lua: As("`window_role`"),
879 doc: "Minimize, toggle-maximize, start-drag, close — what a chrome node asks for on a press.",
880 },
881 Door {
882 rust: "Core::window_title",
883 c: Is("kui_window_title_get"),
884 node: Is("Ctx.windowTitle"),
885 lua: No(GUEST),
886 doc: "What the frame declared, for a driver applying it; a `KuiWindow` applies its own.",
887 },
888 Door {
889 rust: "Core::always_on_top",
890 c: Is("kui_always_on_top_get"),
891 node: Is("Ctx.alwaysOnTop"),
892 lua: As("`env.window.always_on_top`, a reading"),
893 doc: "The same for the level.",
894 },
895 Door {
896 rust: "Core::secure_input",
897 c: Is("kui_secure_input_get"),
898 node: Is("Ctx.secureInput"),
899 lua: No(GUEST),
900 doc: "The same for the secure-input ask: what a driver with its own loop reads to make the platform call; the runner makes it for a `KuiWindow` and `kui_run`.",
901 },
902 Door {
903 rust: "Core::option_as_alt",
904 c: Is("kui_option_as_alt_get"),
905 node: Is("Ctx.optionAsAlt"),
906 lua: No(GUEST),
907 doc: "The same for the Option-as-Alt ask: what a driver with its own loop reads to apply it to its window; the runner applies it for a `KuiWindow` and `kui_run`.",
908 },
909 Door {
910 rust: "Core::take_window_commands",
911 c: Is("kui_take_window_command"),
912 node: Is("Ctx.windowCommands"),
913 lua: No(GUEST),
914 doc: "Drains what the frame asked of the driver: open, close, resize, focus, redraw.",
915 },
916 Door {
917 rust: "Core::window_closed",
918 c: Is("kui_window_closed"),
919 node: Is("Ctx.windowClosed"),
920 lua: No(GUEST),
921 doc: "The driver reports a window gone.",
922 },
923 Door {
924 rust: "Core::dismiss_window",
925 c: Is("kui_window_dismissed"),
926 node: Is("Ctx.windowDismissed"),
927 lua: No(GUEST),
928 doc: "The driver reports a popup dismissed, with why (ADR 0003 step 4).",
929 },
930 Door {
932 rust: "Core::set_theme",
933 c: Is("kui_theme_set"),
934 node: Is("setTheme"),
935 lua: No("read-only: the palette is the host's (ADR 0019)"),
936 doc: "Pins a whole palette.",
937 },
938 Door {
939 rust: "Core::set_accent",
940 c: Is("kui_theme_set_accent"),
941 node: Is("setAccent"),
942 lua: No("as `set_theme`"),
943 doc: "Pins an accent and keeps the OS's base.",
944 },
945 Door {
946 rust: "Ui::theme",
947 c: Is("kui_theme"),
948 node: Is("theme"),
949 lua: As("`env.theme`, a reading"),
950 doc: "The palette in effect (`THEME_ROLES`).",
951 },
952 Door {
953 rust: "Core::set_metrics",
954 c: Is("kui_metrics_set"),
955 node: Is("setMetrics"),
956 lua: No("as `set_theme` (backlog T2)"),
957 doc: "Pins the stock widgets' sizes.",
958 },
959 Door {
960 rust: "Ui::metrics",
961 c: Is("kui_metrics"),
962 node: Is("metrics"),
963 lua: As("`env.metrics`, a reading"),
964 doc: "The sizes in effect (`METRIC_ROLES`).",
965 },
966 Door {
967 rust: "Ui::set_tokens",
968 c: Is("kui_tokens_set"),
969 node: Is("setTokens"),
970 lua: Is("set_tokens"),
971 doc: "Declares the origin's colour and length tokens (ADR 0027).",
972 },
973 Door {
974 rust: "Tokens::derive",
975 c: Is("kui_tokens_derive"),
976 node: As("a colour with `from` in `setTokens`"),
977 lua: As("a colour with `from` in `set_tokens`"),
978 doc: "Adds derived colours to the declared ones (ADR 0028).",
979 },
980 Door {
981 rust: "Ui::tokens",
982 c: As("`kui_token_color` / `kui_token_length`, one name at a time"),
983 node: Is("tokens"),
984 lua: As("`env.tokens`, a reading"),
985 doc: "The tokens in effect, resolved for the appearance.",
986 },
987 Door {
988 rust: "Core::tokens_declared",
989 c: No(
990 "a plugin declares in every `kui_ext_view` and pays the parse; a reader that lets it skip the second is one line, once a plugin asks for it",
991 ),
992 node: No("an app declares once, before its loop"),
993 lua: No("the `tokens` global is declared once, at load"),
994 doc: "Whether an origin declared tokens.",
995 },
996 Door {
998 rust: "Core::set_diagnostics",
999 c: Is("kui_set_diagnostics"),
1000 node: Is("setDiagnostics"),
1001 lua: No(GUEST),
1002 doc: "Turns the per-frame checks on.",
1003 },
1004 Door {
1005 rust: "Core::take_warnings",
1006 c: Is("kui_take_warnings"),
1007 node: Is("warnings"),
1008 lua: No("the host drains and the Lua runner prints"),
1009 doc: "Drains the warnings raised since the last call.",
1010 },
1011 Door {
1012 rust: "Core::warnings_raised",
1013 c: No(
1014 "the C smoke round drains `kui_take_warnings` after each frame; a non-draining reader waits for a C harness that needs one",
1015 ),
1016 node: Is("warningsRaised"),
1017 lua: No(GUEST),
1018 doc: "The warnings raised so far, undrained, which is what an example's self-check reads (ADR 0021).",
1019 },
1020 Door {
1021 rust: "Core::set_devtools",
1022 c: Is("kui_set_devtools"),
1023 node: Is("setDevtools"),
1024 lua: No(GUEST),
1025 doc: "Turns the devtools panel on.",
1026 },
1027 Door {
1028 rust: "Core::devtools",
1029 c: Is("kui_devtools"),
1030 node: Is("devtools"),
1031 lua: No(GUEST),
1032 doc: "Whether it is on.",
1033 },
1034 Door {
1035 rust: "Core::set_devtools_dock",
1036 c: Is("kui_set_devtools_dock"),
1037 node: Is("setDevtoolsDock"),
1038 lua: No(GUEST),
1039 doc: "Where it sits.",
1040 },
1041 Door {
1042 rust: "Core::devtools_dock",
1043 c: Is("kui_devtools_dock"),
1044 node: Is("devtoolsDock"),
1045 lua: No(GUEST),
1046 doc: "Where it sits, read back.",
1047 },
1048 Door {
1049 rust: "Core::host_rect",
1050 c: Is("kui_host_rect"),
1051 node: Is("hostArea"),
1052 lua: No(GUEST),
1053 doc: "Where the frame laid the host out in the window, logical px: the viewport with its origin, which is what tells the app's quads from the dock's (backlog F92).",
1054 },
1055 Door {
1056 rust: "Core::set_devtools_theme",
1057 c: Is("kui_set_devtools_theme"),
1058 node: Is("setDevtoolsTheme"),
1059 lua: No(GUEST),
1060 doc: "Seeds the panel's theme override.",
1061 },
1062 Door {
1063 rust: "Core::set_devtools_key",
1064 c: Is("kui_set_devtools_key"),
1065 node: Is("setDevtoolsKey"),
1066 lua: No(GUEST),
1067 doc: "Respells the chord that moves the keyboard into the panel (`Ctrl+Shift+I` by default).",
1068 },
1069 Door {
1070 rust: "Core::devtools_key",
1071 c: Is("kui_devtools_key"),
1072 node: Is("devtoolsKey"),
1073 lua: No(GUEST),
1074 doc: "That chord, read back in its portable spelling.",
1075 },
1076 Door {
1077 rust: "Ui::devtools_tab",
1078 c: Is("kui_devtools_tab"),
1079 node: As("`<devtoolsTab name label slot/>`"),
1080 lua: As("`devtools_tab { name=, label=, slot= }`"),
1081 doc: "Declares a devtools tab an extension fills through the slot named (ADR 0032).",
1082 },
1083 Door {
1084 rust: "Ui::devtools_tab_with",
1085 c: Is("kui_devtools_tab_open"),
1086 node: As(
1087 "`<devtoolsTab name label>{() => …}</devtoolsTab>`, the function child called only while the tab is on show",
1088 ),
1089 lua: As(
1090 "`devtools_tab { name=, label=, view = function(env) … end }`, called only while the tab is on show",
1091 ),
1092 doc: "Declares a devtools tab the host draws itself, and draws it only while it is on show.",
1093 },
1094 Door {
1095 rust: "Core::devtools_shown_tab",
1096 c: No(
1097 "a C host's open answers whether the tab is on show (`kui_devtools_tab_open`); nothing encodes ahead of the core there",
1098 ),
1099 node: Is("devtoolsShownTab"),
1100 lua: No("the runner's converter reads it for the script (ADR 0032, decision 3)"),
1101 doc: "The declared devtools tab on show, which a data binding reads once a frame to call the tab's function.",
1102 },
1103 Door {
1104 rust: "Core::devtools_selected",
1105 c: Is("kui_devtools_selected"),
1106 node: Is("devtoolsSelected"),
1107 lua: No(GUEST),
1108 doc: "The node the panel's tree tab has selected (ADR 0032, decision 4).",
1109 },
1110 Door {
1111 rust: "Core::devtools_hovered",
1112 c: Is("kui_devtools_hovered"),
1113 node: Is("devtoolsHovered"),
1114 lua: No(GUEST),
1115 doc: "The tree row under the pointer.",
1116 },
1117 Door {
1118 rust: "Core::devtools_picked",
1119 c: Is("kui_devtools_picked"),
1120 node: Is("devtoolsPicked"),
1121 lua: No(GUEST),
1122 doc: "The node the picker is over.",
1123 },
1124 Door {
1125 rust: "Core::set_devtools_pick",
1126 c: Is("kui_set_devtools_pick"),
1127 node: Is("setDevtoolsPick"),
1128 lua: No(GUEST),
1129 doc: "Raises the panel's picker from outside it, or puts it away; raised from a declared tab, the pick lands in `devtools_selected` and the tab stays up.",
1130 },
1131 Door {
1132 rust: "Core::devtools_picking",
1133 c: Is("kui_devtools_picking"),
1134 node: Is("devtoolsPicking"),
1135 lua: No(GUEST),
1136 doc: "Whether the picker is up.",
1137 },
1138 Door {
1139 rust: "Core::set_devtools_selected",
1140 c: Is("kui_set_devtools_selected"),
1141 node: Is("setDevtoolsSelected"),
1142 lua: No(GUEST),
1143 doc: "Selects and reveals a node in the tree tab from outside the panel.",
1144 },
1145 Door {
1146 rust: "Core::set_devtools_tab",
1147 c: Is("kui_set_devtools_tab"),
1148 node: Is("setDevtoolsTab"),
1149 lua: No(GUEST),
1150 doc: "Shows the panel's tab named — one of its own, in any case, or a declared one, as declared — from outside the panel, as the strip's click does; a hidden panel comes back docked.",
1151 },
1152 Door {
1153 rust: "Core::devtools_current_tab",
1154 c: Is("kui_devtools_current_tab"),
1155 node: Is("devtoolsCurrentTab"),
1156 lua: No(GUEST),
1157 doc: "The tab the panel is on, by name.",
1158 },
1159 Door {
1160 rust: "Core::set_devtools_legend",
1161 c: Is("kui_set_devtools_legend"),
1162 node: Is("setDevtoolsLegend"),
1163 lua: No(GUEST),
1164 doc: "The key legend the panel's facts tab shows.",
1165 },
1166 Door {
1167 rust: "Core::set_inspect",
1168 c: Is("kui_set_inspect"),
1169 node: Is("setInspect"),
1170 lua: No(GUEST),
1171 doc: "Turns the per-frame node snapshot behind `nodes` on.",
1172 },
1173 Door {
1174 rust: "Core::nodes",
1175 c: Is("kui_nodes"),
1176 node: Is("nodes"),
1177 lua: No(GUEST),
1178 doc: "The last frame's nodes with what layout and the declarations made of them — a tree view's and an inspector's data.",
1179 },
1180 Door {
1182 rust: "Ui::add_extension",
1183 c: Is("kui_ctx_add_extension"),
1184 node: Is("Ctx.addExtension"),
1185 lua: Is("add_extension"),
1186 doc: "Loads a plugin under a namespace; a `KuiWindow` takes its list at construction (`extensions`).",
1187 },
1188 Door {
1189 rust: "Launcher::extensions",
1190 c: As("`kui_ctx_extension_count` / `kui_ctx_extension_namespace`, one at a time"),
1191 node: Is("Ctx.extensionNamespaces"),
1192 lua: Is("extension_namespaces"),
1193 doc: "The namespaces loaded.",
1194 },
1195 Door {
1199 rust: "Core::frame",
1200 c: As("`kui_frame_begin` … `kui_frame_finish`"),
1201 node: Is("Ctx.frame"),
1202 lua: No(GUEST),
1203 doc: "Runs one frame: the view, layout, the draw list; `KuiWindow.setView` is the windowed form, the runner calling it.",
1204 },
1205 Door {
1206 rust: "Core::output",
1207 c: Is("kui_draw_data"),
1208 node: Is("quads"),
1209 lua: No(GUEST),
1210 doc: "The draw list: quads, clips, fragment and texture draws (`clips`, `fragmentDraws`, `textureDraws` beside `quads` in Node) and the frame's stats.",
1211 },
1212 Door {
1213 rust: "Core::take_pending_events",
1214 c: Is("kui_poll_event"),
1215 node: Is("pollEvents"),
1216 lua: As("`on_event(ev)`, pushed after each frame"),
1217 doc: "What the frame and the input since produced, for `update`.",
1218 },
1219 Door {
1220 rust: "Core::set_time",
1221 c: Is("kui_set_time"),
1222 node: Is("Ctx.setTime"),
1223 lua: No(GUEST),
1224 doc: "The clock the tweens read; a window's runner sets it from the display.",
1225 },
1226 Door {
1227 rust: "Core::env",
1228 c: As("`kui_env_set` and its four siblings, `ENV_FIELDS`' C column"),
1229 node: Is("Ctx.setEnv"),
1230 lua: No(GUEST),
1231 doc: "The host facts written in (the `env` field); a `KuiWindow`'s runner writes its own.",
1232 },
1233 Door {
1234 rust: "Ui::env",
1235 c: No("C is the host, so it writes the facts and has no reading (`ENV_FIELDS`)"),
1236 node: Is("env"),
1237 lua: As("`env`, the view's argument"),
1238 doc: "The facts read back, `ENV_FIELDS` row for row.",
1239 },
1240 Door {
1241 rust: "Core::handle_input",
1242 c: As("`kui_input_cursor` … `kui_input_access`, one per `InputEvent`"),
1243 node: As(
1244 "`Ctx.cursor` … `Ctx.access`, one per `InputEvent`; a `KuiWindow` refuses injection",
1245 ),
1246 lua: No(GUEST),
1247 doc: "Pointer, wheel, key, text, IME, assistive and OS file-drag input; a wheel gesture's latching is `scroll_gesture` (`kui_input_scroll_gesture`, `Ctx.scrollGesture`, backlog F107); `press` / `release` are a click by label (`kui_input_press`, `Ctx.press`); the file drag is `drag_files` / `drop_files` / `drag_cancel` (ADR 0031); a file dialog's answer is `answer_files` (`kui_input_files`, `Ctx.answerFiles`, backlog C51).",
1248 },
1249 Door {
1250 rust: "Core::modifiers",
1251 c: Is("kui_input_modifiers"),
1252 node: Is("Ctx.modifiers"),
1253 lua: No(GUEST),
1254 doc: "The modifier state, reported on its own when the OS does (backlog AR22).",
1255 },
1256 Door {
1257 rust: "Core::release_held_keys",
1258 c: Is("kui_release_held_keys"),
1259 node: As(
1260 "`Ctx.setEnv({focused: false})` releases, as losing the keyboard does for every driver (ADR 0020)",
1261 ),
1262 lua: No(GUEST),
1263 doc: "Lets go of every key the focused sink holds.",
1264 },
1265 Door {
1266 rust: "Core::set_subpixel_text",
1267 c: Is("kui_set_subpixel_text"),
1268 node: No(NEVER_PAINTS),
1269 lua: No(GUEST),
1270 doc: "LCD subpixel coverage for outline glyphs, for a renderer that blends per channel.",
1271 },
1272 Door {
1273 rust: "Core::take_audio_commands",
1274 c: Is("kui_take_audio_commands"),
1275 node: Is("Ctx.audioCommands"),
1276 lua: No(GUEST),
1277 doc: "Drains what the frame asked of the audio device; a `KuiWindow`'s device is the runner's.",
1278 },
1279 Door {
1280 rust: "Core::audio_ended",
1281 c: Is("kui_audio_ended"),
1282 node: Is("Ctx.audioEnded"),
1283 lua: No(GUEST),
1284 doc: "The device reports a playback over.",
1285 },
1286 Door {
1287 rust: "Core::audio_truncated",
1288 c: Is("kui_audio_truncated"),
1289 node: Is("Ctx.audioTruncated"),
1290 lua: No(GUEST),
1291 doc: "The device reports a stop that cut a playback short — a one-shot node's removal becomes `truncated-playback`.",
1292 },
1293 Door {
1294 rust: "Core::audio_refused",
1295 c: Is("kui_audio_refused"),
1296 node: Is("Ctx.audioRefused"),
1297 lua: No(GUEST),
1298 doc: "The device reports a play it would not take — a `refused` sound event and `playback-refused`.",
1299 },
1300 Door {
1304 rust: "Launcher::size",
1305 c: As("`width` / `height` in the `KuiRunConfig` `kui_run_with` takes"),
1306 node: As("`width` / `height` in `WindowOptions`"),
1307 lua: No(GUEST),
1308 doc: "The window's opening size; `min_size` / `max_size` / `chrome` / `text_aa` / `diagnostics` / `frame_latency` are the rest of the set, and each binding's form carries them all (`min_w`, `chrome`, `text_aa`, `diagnostics`, `frame_latency` in C; `minWidth`, `chrome`, `textAa`, `diagnostics`, `frameLatency` in Node). `Launcher::devtools` and `Launcher::core` are the two the others reach another way: `kui_set_devtools` / `setDevtools` on the context, and the context handed to `kui_run_with` *is* the core.",
1309 },
1310 Door {
1311 rust: "Launcher::icon",
1312 c: Is("kui_set_icon"),
1313 node: As("`icon` in `WindowOptions`"),
1314 lua: No(GUEST),
1315 doc: "The icon every window of the app is created with — RGBA pixels and their size — shown by Windows in the title bar, Alt-Tab and the taskbar and by X11's window manager; macOS (the bundle's `.icns`) and Wayland (the `.desktop` file's) have no window icon (backlog F86). `Launcher::icon_resource` is the Windows executable's own icon resource, which wins there — C's `resource` argument, Node's `icon.resource`. C's is a free function called before `kui_run`, for `kui_on_teardown`'s reason.",
1316 },
1317 Door {
1318 rust: "App::teardown",
1319 c: Is("kui_on_teardown"),
1320 node: Is("KuiWindow.onTeardown"),
1321 lua: No(GUEST),
1322 doc: "The window going for good — its close button, Quit from the menu or the dock, a close command on it, a pumped runner ended — heard once, before `run` returns or the process exits, with nothing drawing: the place to keep what the app would lose with the window (backlog F74, the other two hosts under RG1). On macOS a Quit ends the process from inside the loop, so this is the only thing an app runs on ⌘Q — nothing after `run`, `kui_run` or `await runWindowed(...)` does, not even `process.on('exit')`. C's is a free function called before `kui_run`, with the run's `user`, since `kui_run`'s app is three arguments and not a struct. Node's is the window's door, called from inside the pump that saw the window go; `runWindowed` registers its config's `teardown(model)` there, and `createApp`'s `app.teardown()` runs the same one for a headless drive.",
1323 },
1324];
1325
1326#[cfg(test)]
1327mod tests {
1328 use super::*;
1329
1330 #[test]
1338 fn every_rust_spelling_is_a_public_fn() {
1339 let root = std::path::Path::new(env!("CARGO_MANIFEST_DIR")).join("src");
1340 let read = |p: std::path::PathBuf| std::fs::read_to_string(&p).unwrap_or_default();
1341 let mut runtime = read(root.join("runtime.rs"));
1342 for dir in ["runtime", "runtime/devtools"] {
1343 for entry in std::fs::read_dir(root.join(dir)).unwrap() {
1344 let p = entry.unwrap().path();
1345 if p.extension().is_some_and(|e| e == "rs") {
1346 runtime.push_str(&read(p));
1347 }
1348 }
1349 }
1350 let ui = read(root.join("ui.rs"));
1351 let session = read(root.join("session.rs"));
1352 let tokens = read(root.join("tokens.rs"));
1353 let launcher = read(root.join("../../kui-native/src/lib.rs"));
1354 let app_trait = launcher
1357 .split_once("pub trait App {")
1358 .map(|(_, rest)| rest.split_once("\n}\n").map_or(rest, |(body, _)| body))
1359 .unwrap_or_default();
1360 for d in DOORS {
1361 let (ty, name) = d.rust.split_once("::").expect(d.rust);
1362 let src = match ty {
1363 "Ui" => &ui,
1364 "Core" => &runtime,
1365 "SharedResources" => &session,
1366 "Tokens" => &tokens,
1367 "Launcher" => &launcher,
1368 "App" => app_trait,
1369 other => panic!("{}: {other} is not a prefix the table knows", d.rust),
1370 };
1371 let (public, any) = (
1372 format!("{}fn {name}(", if ty == "App" { "" } else { "pub " }),
1373 format!("fn {name}("),
1374 );
1375 assert!(
1376 src.contains(&public) || (ty == "Core" && name == "env"),
1377 "{}: no `{public}` in {ty}'s sources{}",
1378 d.rust,
1379 if src.contains(&any) {
1380 " (a private fn is)"
1381 } else {
1382 ""
1383 }
1384 );
1385 }
1386 }
1387
1388 #[test]
1392 fn rows_are_unique_and_every_no_has_a_reason() {
1393 let mut seen = std::collections::BTreeSet::new();
1394 for d in DOORS {
1395 assert!(seen.insert(d.rust), "{} is two rows", d.rust);
1396 assert!(!d.doc.is_empty(), "{} has no doc", d.rust);
1397 for (binding, cell) in [("C", d.c), ("Node", d.node), ("Lua", d.lua)] {
1398 match cell {
1399 Is(name) => assert!(
1400 !name.is_empty() && !name.contains(' '),
1401 "{} in {binding}: {name:?} is not a name",
1402 d.rust
1403 ),
1404 As(how) | No(how) => assert!(
1405 how.len() >= 12,
1406 "{} in {binding}: {how:?} is not a reason",
1407 d.rust
1408 ),
1409 }
1410 }
1411 }
1412 }
1413
1414 #[test]
1419 fn cells_are_spelled_in_their_bindings_case() {
1420 let snake = |s: &str| {
1421 s.bytes()
1422 .all(|b| b.is_ascii_lowercase() || b == b'_' || b.is_ascii_digit())
1423 };
1424 for d in DOORS {
1425 if let Is(c) = d.c {
1426 assert!(
1427 c.starts_with("kui_") && snake(c),
1428 "{}: C cell {c:?}",
1429 d.rust
1430 );
1431 }
1432 if let Is(n) = d.node {
1433 let n = n
1434 .strip_prefix("Ctx.")
1435 .or_else(|| n.strip_prefix("KuiWindow."))
1436 .unwrap_or(n);
1437 assert!(
1438 !n.contains('_') && n.starts_with(|c: char| c.is_ascii_lowercase()),
1439 "{}: Node cell {n:?}",
1440 d.rust
1441 );
1442 }
1443 if let Is(l) = d.lua {
1444 assert!(snake(l), "{}: Lua cell {l:?}", d.rust);
1445 }
1446 }
1447 }
1448}