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