@qxuken/kui 0.1.0-alpha.40 → 0.1.0-alpha.42
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +415 -0
- package/README.md +4 -3
- package/docs/adr/0010-a-segment-primitive.md +10 -0
- package/docs/adr/0042-a-gradient-is-an-image-the-core-paints.md +15 -3
- package/encoder.js +10 -2
- package/howto.md +39 -13
- package/index.d.ts +18 -4
- package/index.js +6 -2
- package/jsx-runtime.d.ts +26 -10
- package/native.cjs +10 -3
- package/package.json +1 -1
- package/prebuilds/darwin-arm64/kui_node.node +0 -0
- package/prebuilds/linux-arm64/kui_node.node +0 -0
- package/prebuilds/linux-x64/kui_node.node +0 -0
- package/prebuilds/win32-x64/kui_node.node +0 -0
- package/props.md +380 -371
- package/prebuilds/darwin-x64/kui_node.node +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -21,6 +21,421 @@ listed under both (backlog F61, from the alpha.12 field reports: the list
|
|
|
21
21
|
is what the release knows it broke, and a fix it did not think of as one
|
|
22
22
|
was the first bare bump to break an app in five releases).
|
|
23
23
|
|
|
24
|
+
## 0.1.0-alpha.42 (2026-10-07)
|
|
25
|
+
|
|
26
|
+
**What breaks.**
|
|
27
|
+
|
|
28
|
+
- A press after a dead key it does not combine with carries what the
|
|
29
|
+
platform typed in its `text`: German's `^ space` is a Space whose
|
|
30
|
+
`text` is `^`, and `^ z` a `z` whose `text` is `^z`, where they said `" "`
|
|
31
|
+
and `z` — in a key sink's payload and in what an editor inserts (under
|
|
32
|
+
Fixed, RG127). A keymap that binds Space by its `text` rather than its
|
|
33
|
+
`code` sees the accent there.
|
|
34
|
+
- Node: a whole number past 2^53 in a message comes back a `number`,
|
|
35
|
+
where it came back a `BigInt` (RG138).
|
|
36
|
+
- C: `kui_take_menu_action` with a NULL or too-small `out` leaves the
|
|
37
|
+
action queued, where it dropped it; `kui_take_warnings` keeps what does
|
|
38
|
+
not fit `cap` for the next call, where it dropped it; `kui_draw_data`'s
|
|
39
|
+
`fragments` and `textures` are NULL on a frame that draws none, where
|
|
40
|
+
they were a non-NULL pointer to nothing (RG133, RG134, RG131).
|
|
41
|
+
- A text style whose size or line height is under a pixel — 0, negative,
|
|
42
|
+
NaN — shapes at a pixel, where Node and Lua aborted or hung and Rust
|
|
43
|
+
panicked (RG136); a cell grid's rows are a pixel apart at an infinite
|
|
44
|
+
one, where they went to the layout's limit (RG144).
|
|
45
|
+
- Rust: `schema::Door`, `schema::CustomProp` and `schema::ElementDef` gain
|
|
46
|
+
`odin` (under Added, the Odin binding), so a struct literal of one needs
|
|
47
|
+
the field.
|
|
48
|
+
|
|
49
|
+
C stays at ABI 25 (kui.h gains no function and no field; four doors now
|
|
50
|
+
keep what it always promised) and the Node wire at v21 (no frame version).
|
|
51
|
+
|
|
52
|
+
### Added
|
|
53
|
+
|
|
54
|
+
- **An Odin binding, experimental** (`packages/odin`). `kui/c` mirrors
|
|
55
|
+
kui.h declaration by declaration, pinned to the C compiler's layout by
|
|
56
|
+
848 generated `#assert`s. `kui` is the typed layer, generated from
|
|
57
|
+
kui.h and the prop schema:
|
|
58
|
+
- `Spec` and `Text_Style`, one field per schema row;
|
|
59
|
+
- an enum or bit set per family of constants;
|
|
60
|
+
- a door per C function: out-params as results, arrays as slices,
|
|
61
|
+
messages as plain Odin values with `#[derive(Message)]`'s `kind`
|
|
62
|
+
rule.
|
|
63
|
+
|
|
64
|
+
The elements are written by hand: containers close at the end of their
|
|
65
|
+
`if` through `@(deferred_in)`. A C function the hand-written files do
|
|
66
|
+
not call gets a generated door, so the binding covers kui.h whole: 219
|
|
67
|
+
generated, 51 by hand, 2 skipped with their reason.
|
|
68
|
+
`examples/odin/tools/surface.odin` is `surface.c` through it, and calls
|
|
69
|
+
every door, and `examples/odin/tools/conformance.odin` rebuilds the
|
|
70
|
+
scene corpus through `Spec` and the doors, matching the reference report
|
|
71
|
+
byte for byte, as the Rust, Lua, C and Node adapters do.
|
|
72
|
+
`polyline` and `polygon` take points (`[][2]f32`), the count kui.h
|
|
73
|
+
means; a dash or a pivot is a fixed array in a `Maybe` (`[5]f32`,
|
|
74
|
+
`[2]f32`), so a short one cannot be written; and pixels are checked
|
|
75
|
+
against the size beside them.
|
|
76
|
+
|
|
77
|
+
It covers extensions both ways. An Odin host loads a plugin with
|
|
78
|
+
`ctx_add_extension` and `slot`. An Odin plugin is a shared library whose
|
|
79
|
+
seven `kui_ext_*` exports are one line each over `extension.odin`.
|
|
80
|
+
Built with `KUI_PLUGIN` on macOS and Linux, it links no kui and loads
|
|
81
|
+
into any host (on Windows it imports `kui_ffi.dll`, as a C plugin does):
|
|
82
|
+
`nu scripts/odin.nu slots` drives the Odin panel in the C and Rust
|
|
83
|
+
hosts and the C panel in the Odin host.
|
|
84
|
+
|
|
85
|
+
Run it with `nu scripts/odin.nu gen | test | slots | run counter`. It is
|
|
86
|
+
not published. CI's `check` installs a pinned Odin release (`ODIN_VERSION`)
|
|
87
|
+
and runs `gen --check`, `check`, `test` and `slots`, so a header or schema
|
|
88
|
+
change that was not regenerated goes red there. All four also run green
|
|
89
|
+
by hand on Windows x64 and Linux x64. On Windows the binding links
|
|
90
|
+
`kui_ffi.dll.lib`, odin.nu puts `kui_ffi.dll` beside the programs, and
|
|
91
|
+
`gen --check` reads a CRLF checkout as current.
|
|
92
|
+
- `scripts/pack-ffi.nu`: libkui_ffi for every platform kui ships, dynamic
|
|
93
|
+
and static, with `kui.h`, rustc's `native-static-libs` as `link.txt`, a
|
|
94
|
+
tarball each and `SHA256SUMS`. It is for a C or Odin host that links a
|
|
95
|
+
library instead of building the workspace. The machine's own platform
|
|
96
|
+
is built natively. Linux x64 and arm64 (glibc 2.28) and Windows x64 are
|
|
97
|
+
built in a pinned Docker image, with cargo-zigbuild at the release
|
|
98
|
+
workflow's pins and with cargo-xwin. Windows also asks for
|
|
99
|
+
`--accept-msvc-license`, for the CRT and SDK xwin downloads. macOS is
|
|
100
|
+
built on a Mac only. A Windows pack carries windows-targets' import
|
|
101
|
+
libraries (`windows.0.53.0.lib`, `windows.0.52.0.lib`), which its
|
|
102
|
+
`link.txt` names and no SDK has, so a static link finds them. Every
|
|
103
|
+
leg has been run, and a C host linked against each x64 pack alone,
|
|
104
|
+
dynamically and statically, and run; the arm64 pack was read, with no
|
|
105
|
+
arm64 machine to run it on. `kui.h` ships with LF line ends from any
|
|
106
|
+
checkout.
|
|
107
|
+
- `examples/rust/tools/schema-dump.rs`: the prop schema (props,
|
|
108
|
+
composites, elements, events, the verb table, the name lists) as JSON,
|
|
109
|
+
for a binding generated outside Rust.
|
|
110
|
+
- The verb table (`schema::DOORS`) and `docs/props.md` have an Odin
|
|
111
|
+
column beside C's, each spelling held by the Odin generator both ways;
|
|
112
|
+
Node's `protocol()` carries it (`Door.odin`).
|
|
113
|
+
|
|
114
|
+
### Fixed
|
|
115
|
+
|
|
116
|
+
- **A dead key types its accent before a key it does not combine with**
|
|
117
|
+
(backlog RG127, from the Windows and Linux round after alpha.41). With
|
|
118
|
+
German, `^ space` typed a space where it types `^`, `´ space` a space
|
|
119
|
+
where it types `´`, and `^ z` a `z` where it types `^z` — on Windows
|
|
120
|
+
always, and under X11 with `imeOff` on; on US-International, where `'`
|
|
121
|
+
and `"` are dead, a quote could not be typed at all. winit composed it
|
|
122
|
+
right: the runner read a press's text off the logical key, which is
|
|
123
|
+
the key the accent fell back to, and Space's insert was a space
|
|
124
|
+
whatever the press carried. A press's text is now what the platform
|
|
125
|
+
composed, the layout's character where it composed nothing, and Space
|
|
126
|
+
inserts its own. `^ e` was right and is unchanged; with the input
|
|
127
|
+
method on, X11 composes through XIM as before.
|
|
128
|
+
- The docs of F103 (alpha.41) said an animating Windows window behind
|
|
129
|
+
other windows skips its frames. It does not: DWM composes a covered
|
|
130
|
+
window, and it draws at the display's rate, 241 frames a second here,
|
|
131
|
+
as an uncovered one does; minimized, it asks for none (RG45). F103's
|
|
132
|
+
wait holds there only for an acquire that times out. `retry.rs` says so
|
|
133
|
+
now (backlog RG128).
|
|
134
|
+
- **Text is read aloud on Windows and Linux** (backlog RG129, from the
|
|
135
|
+
regression and smoke round after RG127). Every static text — a line of
|
|
136
|
+
text, a list row's content, a drawn title — reached UI Automation with
|
|
137
|
+
an empty Name and AT-SPI with an empty name: AccessKit names a label by
|
|
138
|
+
its value, and kui set only its label. macOS read it all along.
|
|
139
|
+
- **A disclosure or a select opens from Narrator** (RG130). UI
|
|
140
|
+
Automation gives a node with `expanded` its ExpandCollapse pattern in
|
|
141
|
+
place of Invoke, and its Expand and Collapse reached nothing. They are
|
|
142
|
+
the node's click.
|
|
143
|
+
- **A text size or line height of 0 no longer ends the process** (RG136).
|
|
144
|
+
`lineHeight: 0`, `size: 0`, or a size under 0.4 (whose line height
|
|
145
|
+
rounds to 0) aborted a Node or Lua process — cosmic-text asserts a line
|
|
146
|
+
height is not 0 — and a negative one spun its layout; on an `edit`, a
|
|
147
|
+
`cells` and in `measureText` too. Every buffer is shaped at a pixel at
|
|
148
|
+
least. C's door had always read them as unset.
|
|
149
|
+
- C: what kui.h says a door hands out lives as long as it says (RG131–
|
|
150
|
+
RG134). A second `kui_draw_data` in a frame freed the arrays the first
|
|
151
|
+
handed out; `kui_access_runs` freed the strings `kui_access_tree`
|
|
152
|
+
handed out; reading a menu row or asking for a copy freed a taken menu
|
|
153
|
+
action's text; and `kui_take_warnings` dropped what did not fit `cap`,
|
|
154
|
+
where kui.h says the rest wait.
|
|
155
|
+
- A custom editor whose `caret` or `selection_anchor` falls inside a
|
|
156
|
+
character has an access tree (RG135): the run was sliced there and
|
|
157
|
+
panicked, which under C emptied the tree every frame; the position is
|
|
158
|
+
the character's start.
|
|
159
|
+
- Node: `measureText` inside a `<devtoolsTab>` function child no longer
|
|
160
|
+
breaks the frame being encoded (RG137); a message, a `<select>` option
|
|
161
|
+
or a `menuBar` row holding a string cut through an emoji draws its lone
|
|
162
|
+
surrogate as U+FFFD rather than failing the frame, and `dir: null` is
|
|
163
|
+
absent like every other null prop (RG138, RG140).
|
|
164
|
+
|
|
165
|
+
### Native verification
|
|
166
|
+
|
|
167
|
+
The by-hand round alpha.6 introduced (backlog R4), on 2026-10-07, over
|
|
168
|
+
the rounds after the alpha.41 tag — the Odin binding and `pack-ffi.nu`,
|
|
169
|
+
RG127 and RG128 from the Windows and Linux round after alpha.41, and the
|
|
170
|
+
regression and smoke round after RG127 (RG129–RG138) — with alpha.42's
|
|
171
|
+
pre-tag pass over them on the Mac: the mechanical round, then four
|
|
172
|
+
read-only reviews of the diff since alpha.41 (the Odin binding; the C
|
|
173
|
+
doors and `pack-ffi.nu`; the runner's keys, the access bridge, the text
|
|
174
|
+
floor and Node; the docs), each claim probed. They filed RG140–RG144,
|
|
175
|
+
built before the tag (a `<select>` option or menu bar row cut through an
|
|
176
|
+
emoji failing the Node frame, `kui_draw_data` while a frame built losing
|
|
177
|
+
the finished frame's fragment draws, the Odin drains freeing the strings
|
|
178
|
+
they returned, Odin's popups, unchecked slices and acronym kinds, a cell
|
|
179
|
+
grid's infinite line height), and RG145, open.
|
|
180
|
+
|
|
181
|
+
**macOS**, the pre-tag pass. fmt and clippy are clean; `cargo test
|
|
182
|
+
--workspace --features kui-core/conformance`: **1856 tests over 139
|
|
183
|
+
suites**. The C round passes, and so do the **57 scenes**, the Odin
|
|
184
|
+
binding's `gen --check`, `check`, `test` and `slots`, Node's tests under
|
|
185
|
+
`KUI_CONFORMANCE_REQUIRED=1` (**215 of 215**), `npm run gen` with no
|
|
186
|
+
diff, the headless round and the book. The windowed round with Node's:
|
|
187
|
+
**124 windows**. The AX audit: **106/106**. RG127's dead keys, which the
|
|
188
|
+
Windows and Linux round could not reach on a Mac: twelve sequences typed
|
|
189
|
+
into the `edit` example through `CGEventPostToPid` and read back through
|
|
190
|
+
AX, each as AppKit composes it (`⌥e e` is `é`, `⌥e space` `´`, `⌥e z`
|
|
191
|
+
`´z`). The bench guard against the alpha.41 tag: **green**, the guarded
|
|
192
|
+
rows −1.2 to −0.3%, RG126's warm cell grid −0.4%.
|
|
193
|
+
|
|
194
|
+
**Windows 11 x64 (MSVC) and Linux x64 (WSL Ubuntu 24.04), rustc
|
|
195
|
+
1.99.0**, on the tree with the pre-tag fixes and `pack-ffi.nu`'s. fmt
|
|
196
|
+
and `cargo clippy --workspace --all-targets --features
|
|
197
|
+
kui-core/conformance -- -D warnings` are clean on both. `cargo test
|
|
198
|
+
--workspace --features kui-core/conformance`: **1857 tests over 140
|
|
199
|
+
suites** on Windows (5 ignored), **1853 over 139** on Linux (4
|
|
200
|
+
ignored), **0 failed**. `cargo audit --deny warnings` is clean over
|
|
201
|
+
`Cargo.lock`'s 444 crates. `pack-ffi.nu` ran every leg but macOS's: native
|
|
202
|
+
on both, and linux-x64, linux-arm64 and win32-x64 (cargo-xwin) in its
|
|
203
|
+
container. A C host linked against each x64 pack alone, dynamically and
|
|
204
|
+
statically, ran; the arm64 pack was read, not run. It found three things,
|
|
205
|
+
fixed before the tag (RG145): a CRLF `kui.h` from a CRLF checkout, the
|
|
206
|
+
closing table lost off a terminal, and a `docker` that could not be
|
|
207
|
+
spawned stopping the script. Earlier the same day, before the pre-tag
|
|
208
|
+
fixes, the Odin binding's four steps passed on both, and the regression
|
|
209
|
+
and smoke round after RG127 ran the windowed smoke and walked the
|
|
210
|
+
accessibility tree through UI Automation and AT-SPI.
|
|
211
|
+
|
|
212
|
+
## 0.1.0-alpha.41 (2026-10-07)
|
|
213
|
+
|
|
214
|
+
**What breaks.**
|
|
215
|
+
|
|
216
|
+
- A leaf that declares `tooltip` — `line`, `polygon`, `path`, `cells`,
|
|
217
|
+
`image`, `edit`, in any binding, or a Rust leaf whose spec says
|
|
218
|
+
`NodeSpec::tooltip` — draws its hint while hovered, where it drew
|
|
219
|
+
nothing; so does a C `kui_fragment*` node with `KuiSpec.tooltip`.
|
|
220
|
+
- A `dash` gap the round-capped marks overlap closes: `dash = {2, 2}` at
|
|
221
|
+
a width of 8 draws a solid line where it drew 8 px dots every 4 px.
|
|
222
|
+
- With a fallback list set, `Mono` text asks the app's fallback faces
|
|
223
|
+
before the machine's other monospaced ones, so a character may draw in
|
|
224
|
+
another face, and a single-weight monospaced face draws its bold
|
|
225
|
+
synthesized instead of in the platform's proportional face.
|
|
226
|
+
- A cell grid whose family has no `M` draws its own glyphs where its face
|
|
227
|
+
puts them, no longer centred as a fallback's.
|
|
228
|
+
- On a line past 4 KB, a tab after more than ~512 bytes with none moves
|
|
229
|
+
onto the line's tab stops, up to a tab's width, and the rest of the
|
|
230
|
+
line with it.
|
|
231
|
+
- Rust: `schema::PropsOut` gains `ime_off` (under Added, F125), so a
|
|
232
|
+
struct literal of it needs the field or `..Default::default()`; so do
|
|
233
|
+
`conformance::Expect` and `conformance::Output`, behind the
|
|
234
|
+
`conformance` feature.
|
|
235
|
+
- npm: `@qxuken/kui` bundles no darwin-x64 prebuild. On an Intel Mac (or
|
|
236
|
+
an x64 Node under Rosetta),
|
|
237
|
+
build the addon (`cargo build -p kui-node --release`) and point
|
|
238
|
+
`KUI_NODE_LIB` at it; the Rust crates are unchanged there.
|
|
239
|
+
|
|
240
|
+
C stays at ABI 25 (`kui_set_ime_off` / `kui_ime_off_get` are new
|
|
241
|
+
functions) and the Node wire at v21 (a root prop, no frame version).
|
|
242
|
+
|
|
243
|
+
A leaf's hint is drawn now, and the four paint changes after it are each
|
|
244
|
+
what the code always meant to draw: a hint the docs told you to put on a
|
|
245
|
+
box around the leaf, a dotted line that was a lumpy solid one at a quad a
|
|
246
|
+
dot, a fallback list that `Mono` text never asked, a grid's own glyphs
|
|
247
|
+
treated as a stranger's, and a tab measured from where its chunk began
|
|
248
|
+
instead of where the line did. Each moves pixels an app may have written
|
|
249
|
+
to, so each is listed.
|
|
250
|
+
|
|
251
|
+
### Added
|
|
252
|
+
|
|
253
|
+
- **A window can take the keyboard as keys, with the input method off**
|
|
254
|
+
(backlog F125, from kawoosh's wish list). `ui.ime_off(true)` / a root
|
|
255
|
+
`imeOff` / `ime_off = true` / `kui_set_ime_off(ctx, true)` turns the
|
|
256
|
+
platform's input method off in the window: no composition and no
|
|
257
|
+
candidate window, and on a Mac no dead key waiting for the next and no
|
|
258
|
+
press-and-hold — which is an input method too, so a held `j` repeats
|
|
259
|
+
and a held `e` opens no accent picker, whatever the user's
|
|
260
|
+
`ApplePressAndHoldEnabled` says. A `key` event's `text` is still the
|
|
261
|
+
layout's character. What a modal editor's normal mode wants; its
|
|
262
|
+
insert mode stops declaring it and gets accents, dead keys and the IME
|
|
263
|
+
back. Frame state in `optionAsAlt`'s shape, default off; the runner
|
|
264
|
+
applies it on change through winit's `set_ime_allowed`, so winit's
|
|
265
|
+
`keyDown:` stops calling `interpretKeyEvents:`, where macOS composes. A
|
|
266
|
+
key pressed while it was off keeps it off until it comes up, so the
|
|
267
|
+
`i` that switches to insert mode, held, keeps typing `iiii` rather
|
|
268
|
+
than opening the picker over its own repeats; the next fresh press in
|
|
269
|
+
insert mode gets the picker. A composition open when it turns off is
|
|
270
|
+
dropped, and ends in the view as an empty `preedit` — as one does now
|
|
271
|
+
when the user switches input source mid-composition, which used to
|
|
272
|
+
leave the preedit drawn. On Windows and Linux the window's IME is
|
|
273
|
+
disabled the same way, and only that: a dead key there is the
|
|
274
|
+
layout's, which winit composes whatever the IME says, and it still
|
|
275
|
+
composes. `Ctx.imeOff()` / `kui_ime_off_get` read the ask
|
|
276
|
+
back; `modal_editor` declares it in normal mode. *What you can
|
|
277
|
+
delete:* the README line telling a Mac user of a modal editor to run
|
|
278
|
+
`defaults write -g ApplePressAndHoldEnabled -bool false`, and any
|
|
279
|
+
per-mode IME switching an app did by hand.
|
|
280
|
+
|
|
281
|
+
### Changed
|
|
282
|
+
|
|
283
|
+
- **Intel Macs lose their Node prebuild.** The package ships the addon
|
|
284
|
+
for linux-x64, linux-arm64, darwin-arm64 and win32-x64; the release
|
|
285
|
+
workflow's darwin-x64 leg and `release-local.nu`'s are gone. On an
|
|
286
|
+
Intel Mac `require('@qxuken/kui')` fails with the loader's not-found
|
|
287
|
+
error, which now says the prebuild was dropped and how to build one.
|
|
288
|
+
`kui-native`, `kui-ffi` and the rest still build and run there; only
|
|
289
|
+
the bundled `.node` is gone.
|
|
290
|
+
|
|
291
|
+
### Fixed
|
|
292
|
+
|
|
293
|
+
- **A leaf draws its tooltip** (backlog RG113). The hint floats as its
|
|
294
|
+
node's last child, and a leaf has none, so a hovered wedge, path, line,
|
|
295
|
+
grid, image or editor with a `tooltip` showed nothing — it was tracked
|
|
296
|
+
and spoken, not drawn. It now floats beside the leaf, anchored to it
|
|
297
|
+
(`FloatAnchor::Node`), and lands below the leaf's box as a box's hint
|
|
298
|
+
lands below the box: outside every clip, outside layout, flipped above
|
|
299
|
+
near the window's bottom, and only while the pointer is on the stroke
|
|
300
|
+
or inside the outline. In all four bindings — `NodeSpec::tooltip`, the
|
|
301
|
+
JSX and Lua prop, `KuiSpec.tooltip` on C's leaf doors. A float anchored
|
|
302
|
+
to a node now honours `fit` as a parent-anchored one does. On a leaf
|
|
303
|
+
the drawn string is its description, so a leaf that declares a
|
|
304
|
+
`description` after its `tooltip` draws that.
|
|
305
|
+
- **An animating window whose surface skips its frames waits between
|
|
306
|
+
tries** (backlog F103). A skipped frame returns at once, with no
|
|
307
|
+
drawable to wait for and no vsync behind it, so where the platform
|
|
308
|
+
never says a window is covered — Windows behind other windows, Wayland,
|
|
309
|
+
an acquire that times out — an animation asked for its next frame on
|
|
310
|
+
the loop's very next turn: 82,000 views a second at a core, measured on
|
|
311
|
+
a Mac with every frame forced to skip and no display link. It waits a
|
|
312
|
+
retry (16 ms) after a skip now — 60 a second at 2% — and runs at the
|
|
313
|
+
display's rate again from the first frame that lands. A window macOS
|
|
314
|
+
calls covered still asks for nothing at all. On Windows the timer that
|
|
315
|
+
keeps an animation going through a title-bar drag paces the same tries
|
|
316
|
+
at its own interval, 10 to 16 ms.
|
|
317
|
+
- **A tab on a long line stops where the line's stops are** (backlog
|
|
318
|
+
RG76). On a line past 4 KB, a tab that followed more than half a chunk
|
|
319
|
+
without one measured from its chunk's start. Such a chunk now ends
|
|
320
|
+
after that tab, and the line gives the tab the advance that reaches its
|
|
321
|
+
next stop — exact once the text since the previous tab has been on
|
|
322
|
+
screen, and as near as the rest of the line's estimate before that.
|
|
323
|
+
Wrapped rows carry the same advance.
|
|
324
|
+
- **`measure_text` leaves a drawn text's rows alone** (backlog RG76).
|
|
325
|
+
Measuring, between frames, a text a node drew at another width
|
|
326
|
+
re-wrapped the run they share, so that node's `caret_rect` and
|
|
327
|
+
`text_hit` answered from the measured rows until the next frame wrapped
|
|
328
|
+
it back. The measure lays out a copy at its own width, kept for the
|
|
329
|
+
next measure there.
|
|
330
|
+
- **`Mono` text asks the app's fallback fonts straight after its own
|
|
331
|
+
face** (backlog RG118). cosmic-text's generic monospace family walks
|
|
332
|
+
every installed monospaced face that has the character before the
|
|
333
|
+
lists `set_fallback_fonts` joins — on a Mac, Hebrew in `Mono` came out
|
|
334
|
+
in Courier New *Italic* with Arial named. While a list is set, `Mono`
|
|
335
|
+
is shaped as the face it is pinned to, by name, so the order is that
|
|
336
|
+
face, the app's names, then the platform's. With no list nothing
|
|
337
|
+
changes.
|
|
338
|
+
- **A grid tells its family's glyphs by the family's name** (backlog
|
|
339
|
+
RG118). It read the family's face off the face `M` shaped with, and a
|
|
340
|
+
symbols-only or CJK-only family has no `M`, so its own glyphs were
|
|
341
|
+
taken for a fallback's — centred, and asked of a monospaced face first.
|
|
342
|
+
- **A new fallback list or a font rescan draws every window of the
|
|
343
|
+
session** (backlog RG118). `set_fallback_fonts` and
|
|
344
|
+
`reload_system_fonts` asked for a frame of the window they were called
|
|
345
|
+
through alone; another window shaped again whenever something else drew
|
|
346
|
+
it. Each window that has drawn now owes a frame (`animating()`) while
|
|
347
|
+
the session's fonts are newer than the text it shaped.
|
|
348
|
+
- **Dash dots that overlap make one mark** (backlog RG118). A gap no
|
|
349
|
+
wider than the stroke is closed by the round caps either side of it,
|
|
350
|
+
and `{2, 2}` at a width of 8 was 8 px dots every 4 px — a solid line
|
|
351
|
+
drawn lumpy, at a quad a dot. Such a gap now closes and the marks
|
|
352
|
+
either side are one mark; a pattern with no gap left draws solid. A
|
|
353
|
+
pattern whose gaps show draws exactly as before.
|
|
354
|
+
- **A long line's placed tab answers the caret and the click where it
|
|
355
|
+
is drawn** (backlog RG122, from the pre-tag pass). A line ending in such
|
|
356
|
+
a tab has its end caret, and a selection's end, at the line's width —
|
|
357
|
+
it fell short of the width in a monospaced face and past it in a
|
|
358
|
+
proportional one, and wrapped rows used the chunk's own narrower tab —
|
|
359
|
+
and a click answers the tab before the middle of the drawn tab and the
|
|
360
|
+
byte after it from there, where both halves answered the byte after.
|
|
361
|
+
- **A pinned `Mono` keeps to its face at every weight, and follows the
|
|
362
|
+
fonts the app loads and removes** (backlog RG123, from the pre-tag
|
|
363
|
+
pass). A single-weight monospaced face was passed over for bold and set
|
|
364
|
+
in the platform's proportional face; it now draws in itself, with bold
|
|
365
|
+
synthesized. A pinned family whose only face the app removed left
|
|
366
|
+
`Mono` naming nothing, and one loaded after the list was set was never
|
|
367
|
+
pinned; both now move the pin, and every window shapes again.
|
|
368
|
+
- **A C fragment draws its tooltip** (backlog RG124, from the pre-tag
|
|
369
|
+
pass). The four `kui_fragment*` doors tracked and spoke
|
|
370
|
+
`KuiSpec.tooltip` and floated nothing, where JSX and Lua drew it.
|
|
371
|
+
- The docs of a `gradient` stop whose `$token` misses say what it does:
|
|
372
|
+
`unknown-token` is raised and the stop is left out, so a gradient left
|
|
373
|
+
with fewer than two stops draws nothing over its `bg` — no error, and
|
|
374
|
+
no fade nobody wrote. ADR 0042's amendment says why it stays (backlog
|
|
375
|
+
RG118).
|
|
376
|
+
|
|
377
|
+
**What you can delete.** A box wrapped around a `line`, `polygon` or
|
|
378
|
+
`path` only to carry its `tooltip`; a pattern stretched by hand so a
|
|
379
|
+
thick stroke's dots would not touch; a second `set_fallback_fonts` (or a
|
|
380
|
+
redraw) sent through every other window of the session.
|
|
381
|
+
|
|
382
|
+
### Native verification
|
|
383
|
+
|
|
384
|
+
The by-hand round alpha.6 introduced (backlog R4), on 2026-10-07, over
|
|
385
|
+
the rounds after the alpha.40 tag — `imeOff` (F125), F103's skipped
|
|
386
|
+
half, RG76, RG113 and RG118, and the darwin-x64 prebuild dropped — with
|
|
387
|
+
a regression pass over them first: the mechanical round, then three
|
|
388
|
+
read-only reviews in worktrees (text and fonts; core paint, layout and
|
|
389
|
+
bindings; the runner, the release machinery and the docs), each claim
|
|
390
|
+
probed with a test before anything changed. They filed five: RG122–RG125,
|
|
391
|
+
built before the tag (a long line's placed tab answering the caret and
|
|
392
|
+
the click where its run had it, a pinned `Mono` asked at weights its face
|
|
393
|
+
lacks and not re-pinned when the app's fonts move, a C fragment's
|
|
394
|
+
tooltip never drawn, and `imeOff`'s docs promising no dead keys on
|
|
395
|
+
Windows and Linux, where winit composes them whatever the IME says), and
|
|
396
|
+
RG126, open: `cells_200x50_warm`, unguarded, 3 to 5% slower, bisected to
|
|
397
|
+
the grid's family-by-name check and not yet explained. F103 itself was
|
|
398
|
+
measured in a window first: on macOS a hidden animating window already
|
|
399
|
+
built nothing, and with every frame forced to skip and no display link
|
|
400
|
+
the probe went from 82,000 frames a second at a core to 60 at 2%. This
|
|
401
|
+
round ran on the Mac alone; Windows and Linux did not run it for this
|
|
402
|
+
tag, so F125's `set_ime_allowed` there and F103 under Windows' drag
|
|
403
|
+
timer are by reading.
|
|
404
|
+
|
|
405
|
+
**macOS 27.0.1 on an M3 Pro MacBook Pro, rustc 1.99.0 (the toolchain
|
|
406
|
+
CI runs), Node 26.10.0, nu 0.116.1**, on the release commit's tree.
|
|
407
|
+
`cargo fmt --all --check` and `cargo clippy --workspace --all-targets
|
|
408
|
+
--features kui-core/conformance -- -D warnings` are clean, and so is
|
|
409
|
+
`cargo audit --deny warnings`. `cargo test --workspace --features
|
|
410
|
+
kui-core/conformance`: **1844 tests over 138 suites, 0 failed** (4
|
|
411
|
+
ignored). The C round, `cbuild --run`, passes its five checks; the
|
|
412
|
+
corpus passes its **57 scenes** in four adapters, the `path` scene now
|
|
413
|
+
resting on a tooltip wedge; the ABI is **25**. Node's `node --test
|
|
414
|
+
test.mjs` under `KUI_CONFORMANCE_REQUIRED=1`: **212 of 212**. `npm run
|
|
415
|
+
gen` leaves no diff, the examples typecheck and their lockfile installs,
|
|
416
|
+
the headless round passes all **35 drives**, the book builds and
|
|
417
|
+
`scripts/book-examples.nu --check` passes.
|
|
418
|
+
|
|
419
|
+
**The windowed round**, `smoke -- --node`, twice — before the fixes and
|
|
420
|
+
on the release tree: **51 Rust examples and the eleven Node examples,
|
|
421
|
+
each on both bases, 120 frames each, every one exiting 0** — 124
|
|
422
|
+
windows, eight at a time, in 34.2 and 52.3 s, the second beside another
|
|
423
|
+
session's builds — and `counter`, `host`, `c_panel` and `lua_panel` by
|
|
424
|
+
hand under `KUI_SMOKE_FRAMES=120`, each exiting 0 with nothing on
|
|
425
|
+
stderr: **128 windows over five hosts.** `target/debug/examples` was
|
|
426
|
+
pruned first (12,280 files), the alpha.36 trap. The AX audit:
|
|
427
|
+
**106/106** on both trees, the audited window raised to the front by its
|
|
428
|
+
pid first, and no warning on the fixture's stderr.
|
|
429
|
+
|
|
430
|
+
**The bench guard** against the alpha.40 tag: **green**, none of the 8
|
|
431
|
+
guarded rows more than 10% slower — every one between −1.0% and +0.6%
|
|
432
|
+
(the worst guarded run-to-run spread 2.8%), `frame_10k_segments` +0.3%
|
|
433
|
+
with RG118's dash — beside other processes using ~500% CPU, so the
|
|
434
|
+
medians are not the README's and its table is kept as it was. Of the
|
|
435
|
+
unguarded rows the frame bench's moved by at most +1.7%; the `cells`
|
|
436
|
+
bench's `warm` row read +6.0% (±1.4%) against the tag, +3.8% against
|
|
437
|
+
alpha.40 with F125 merged, and is RG126.
|
|
438
|
+
|
|
24
439
|
## 0.1.0-alpha.40 (2026-10-07)
|
|
25
440
|
|
|
26
441
|
**What breaks.**
|
package/README.md
CHANGED
|
@@ -24,9 +24,10 @@ absent. Ranges do not pin a prerelease — `^0.1.0-alpha.8` and `~0.1.0-alpha.8`
|
|
|
24
24
|
both admit every later alpha of the same `0.1.0` — so an app that wants the
|
|
25
25
|
version it tested writes that version exactly and commits its lockfile.
|
|
26
26
|
|
|
27
|
-
The tarball bundles the native addon for linux-x64, linux-arm64, darwin-arm64
|
|
28
|
-
|
|
29
|
-
`process.platform`-`process.arch`. On any other platform
|
|
27
|
+
The tarball bundles the native addon for linux-x64, linux-arm64, darwin-arm64
|
|
28
|
+
and win32-x64 under `prebuilds/`; `native.cjs` picks the one matching
|
|
29
|
+
`process.platform`-`process.arch`. On any other platform — an Intel Mac
|
|
30
|
+
among them, since 0.1.0-alpha.41 — build it from the
|
|
30
31
|
repo (`cargo build -p kui-node --release`) and set `KUI_NODE_LIB` to the
|
|
31
32
|
resulting library.
|
|
32
33
|
|
|
@@ -456,6 +456,16 @@ and with a round cap its `4 4` at a width of 4 is a solid line, which
|
|
|
456
456
|
is the first thing anyone writes. The first mark's cap sits where the
|
|
457
457
|
solid stroke's would.
|
|
458
458
|
|
|
459
|
+
**A gap the dots overlap closes** (2026-10-07, backlog RG118). A dot is
|
|
460
|
+
as wide as the stroke whatever its mark says, in the same period, so
|
|
461
|
+
where a mark and its gap together come to no more than the width the
|
|
462
|
+
dots meet: as first built, `{2, 2}` at a width of 8 was 8 px dots every
|
|
463
|
+
4 px, a lumpy solid line at a quad a dot. Clamping the dot to its mark
|
|
464
|
+
cannot be drawn, and growing the period to keep the gap moves every
|
|
465
|
+
dotted line whose dots do not touch. So the gap closes and the marks
|
|
466
|
+
either side of it are one (`Dash::cut`); a pattern with no gap left is
|
|
467
|
+
solid. A gap that is seen is untouched.
|
|
468
|
+
|
|
459
469
|
**The same pattern on a `path`.** A path's stroke is a mask
|
|
460
470
|
([ADR 0040](0040-a-path-is-a-mask-in-the-atlas.md), whose decision 3
|
|
461
471
|
left `dash` to V2), so the centre lengths go to the rasterizer and the
|
|
@@ -318,9 +318,21 @@ options*, and decisions 1–4 and 6–11 stand as written.
|
|
|
318
318
|
nobody spells, an unknown field, fewer than two stops in the list or
|
|
319
319
|
a number that is not one is an error from `gradient::parse_with`,
|
|
320
320
|
with the field named. What still draws nothing in silence is a
|
|
321
|
-
gradient that *parsed* and has nothing to paint —
|
|
322
|
-
|
|
323
|
-
|
|
321
|
+
gradient that *parsed* and has nothing to paint — fewer than two
|
|
322
|
+
stops left once those whose token missed are taken out (each raised
|
|
323
|
+
as `unknown-token`), or one built in Rust or C with one stop or a
|
|
324
|
+
NaN. No warning code was added.
|
|
325
|
+
|
|
326
|
+
*Weighed again (2026-10-07, backlog RG118).* The count is of the
|
|
327
|
+
list, so `[$peach, $peech]` parses and draws nothing. A missed stop
|
|
328
|
+
could instead keep its place painted transparent, so the gradient
|
|
329
|
+
still draws; it stays left out. A missed token leaves any other slot
|
|
330
|
+
as if it were not declared (a `bg`, a keyframe's stop, an
|
|
331
|
+
entrance), and a stand-in here would paint a colour nobody wrote — a
|
|
332
|
+
fade to nothing that reads as intended, where a box with no gradient
|
|
333
|
+
over its `bg` reads as the mistake it is beside the `unknown-token`
|
|
334
|
+
that names it. Tokens have no fallback of their own to paint instead.
|
|
335
|
+
The docs of the row say so.
|
|
324
336
|
- **The atlas holds straight alpha** (open question 1). An `Image`
|
|
325
337
|
quad's shader multiplies the texel's rgb by the tint and its alpha by
|
|
326
338
|
the coverage separately, so the texels are straight. The raster mixes
|
package/encoder.js
CHANGED
|
@@ -395,14 +395,15 @@ export function createEncoder(P) {
|
|
|
395
395
|
// protocol kind (no names or shapes hardcoded here); only composites (the
|
|
396
396
|
// pad family, border, overflow bits, float) and the constructor-ordering
|
|
397
397
|
// specials (dir, size) have hand-written stanzas, mirroring binary.rs.
|
|
398
|
-
// `key` rides along as P_KEY; `isRoot` admits `title`, `alwaysOnTop`, `secureInput`, `optionAsAlt` and `windows` (and drops `key`);
|
|
398
|
+
// `key` rides along as P_KEY; `isRoot` admits `title`, `alwaysOnTop`, `secureInput`, `optionAsAlt`, `imeOff` and `windows` (and drops `key`);
|
|
399
399
|
// `admit`, when given, is the only names written (a closed composite's
|
|
400
400
|
// rows — the rest were already reported by checkProps).
|
|
401
401
|
function props(p, key, isRoot, admit) {
|
|
402
402
|
const np = fi++;
|
|
403
403
|
let n = 0;
|
|
404
404
|
// dir and size first: the decoder constructs spec/style from them.
|
|
405
|
-
|
|
405
|
+
// `!= null`: a null dir is absent, as every other null prop is.
|
|
406
|
+
if (p.dir != null && p.dir !== 'column') {
|
|
406
407
|
// `table` is a column whose rows' cells line up (ADR 0033).
|
|
407
408
|
const dir = p.dir === 'row' ? 1 : p.dir === 'table' ? 2 : undefined;
|
|
408
409
|
if (dir === undefined) throw new Error(`bad dir ${JSON.stringify(p.dir)} (row | column | table)`);
|
|
@@ -527,6 +528,13 @@ export function createEncoder(P) {
|
|
|
527
528
|
n++;
|
|
528
529
|
}
|
|
529
530
|
break;
|
|
531
|
+
case 'imeOff':
|
|
532
|
+
// And again (backlog F125).
|
|
533
|
+
if (isRoot && v) {
|
|
534
|
+
f[fi++] = PR.imeOff.id;
|
|
535
|
+
n++;
|
|
536
|
+
}
|
|
537
|
+
break;
|
|
530
538
|
case 'optionAsAlt': {
|
|
531
539
|
// Root only; a side by its number, `OptionAsAlt::index` (backlog
|
|
532
540
|
// F113). "none" is the default and writes nothing, as `false`
|
package/howto.md
CHANGED
|
@@ -61,7 +61,9 @@ a nine-point curve over ~50 px spans is ~60 quads.
|
|
|
61
61
|
marks with 4 px gaps, `dash={4}` the same length for both, and four
|
|
62
62
|
lengths are a dash-dot. The lengths are what you see — every mark has the
|
|
63
63
|
stroke's round caps — so a mark no longer than the stroke is wide is a
|
|
64
|
-
dot: `width={3} dash={[3, 5]}` is a dotted line.
|
|
64
|
+
dot: `width={3} dash={[3, 5]}` is a dotted line. A dot is as wide as the
|
|
65
|
+
stroke, so a gap the dots overlap closes: `width={8} dash={[2, 2]}` is a
|
|
66
|
+
solid line. The pattern runs along
|
|
65
67
|
the whole stroke, round corners and along a `curve`. For marching ants,
|
|
66
68
|
grow `dashOffset` from a tick; the marks move towards the first point.
|
|
67
69
|
A dashed line costs a quad per mark, and is still hit in its gaps.
|
|
@@ -305,7 +307,9 @@ text's own family has no glyph for goes to the first of them that has
|
|
|
305
307
|
it, and only then to the platform's list — whose first choice on macOS
|
|
306
308
|
is the system's interface face, so Cyrillic in a Latin-only monospaced
|
|
307
309
|
family comes out proportional. The list is the session's, for every
|
|
308
|
-
family and every kind of text; `[]` is the platform's alone.
|
|
310
|
+
family and every kind of text; `[]` is the platform's alone. `mono`
|
|
311
|
+
text asks it straight after its own face, ahead of the machine's other
|
|
312
|
+
monospaced faces, which it walks first when there is no list. Set it
|
|
309
313
|
when the choice changes, not every frame with a new list: a new list
|
|
310
314
|
shapes every text again (the same one twice costs nothing). A cell grid
|
|
311
315
|
goes one step further by itself: with no fallback of yours that has the
|
|
@@ -1134,20 +1138,40 @@ macOS's press-and-hold: holding a letter offers its accents (`e` → `é è
|
|
|
1134
1138
|
ê`) instead of repeating it, and a letter with no accents does nothing
|
|
1135
1139
|
at all — on by default, and off only on a machine whose owner turned it
|
|
1136
1140
|
off, which is why it works on one Mac and not the next. Every other
|
|
1137
|
-
platform repeats.
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1141
|
+
platform repeats. The setting is the user's — the read that decides is
|
|
1142
|
+
HIToolbox's, of the user's global preference by name, and no
|
|
1143
|
+
per-process default reaches it (F69 built a door that pinned one; RG15
|
|
1144
|
+
found it inert and RG16 removed it — the backlog archive has the
|
|
1145
|
+
measurements) — but press-and-hold is an *input method*, and a window
|
|
1146
|
+
can take the keyboard with its input method off. Declare `imeOff` on the
|
|
1147
|
+
root while your keys are commands (Rust `ui.ime_off(true)`, Lua
|
|
1148
|
+
`ime_off = true` on the root table, C `kui_set_ime_off(ctx, true)`):
|
|
1149
|
+
|
|
1150
|
+
```rust
|
|
1151
|
+
// Normal mode is a keymap; insert mode types text.
|
|
1152
|
+
ui.ime_off(self.mode == Mode::Normal);
|
|
1153
|
+
```
|
|
1154
|
+
|
|
1155
|
+
A held `j` then repeats, a held `e` opens nothing, and an IME left on
|
|
1156
|
+
no longer eats the keymap — nor, on a Mac, a dead key; each key still
|
|
1157
|
+
carries the layout's character as its `text`. On Windows and Linux a
|
|
1158
|
+
dead key is the layout's and still composes: winit composes it whatever
|
|
1159
|
+
the IME says. Stop declaring it and insert mode has
|
|
1160
|
+
accents, dead keys and the IME back. A key held across the switch — the
|
|
1161
|
+
`i` that enters insert mode — keeps repeating until it comes up, so the
|
|
1162
|
+
picker comes from the next fresh press. It is frame state: declare it on
|
|
1163
|
+
every frame the mode wants it.
|
|
1164
|
+
|
|
1165
|
+
The user can still turn press-and-hold off for every app:
|
|
1143
1166
|
|
|
1144
1167
|
```
|
|
1145
1168
|
defaults write -g ApplePressAndHoldEnabled -bool false
|
|
1146
1169
|
```
|
|
1147
1170
|
|
|
1148
|
-
and a relaunch
|
|
1149
|
-
|
|
1150
|
-
|
|
1171
|
+
and a relaunch.
|
|
1172
|
+
|
|
1173
|
+
[`imeOff`](props.md#composite-props-hand-written-per-binding) ·
|
|
1174
|
+
[`examples/rust/apps/modal_editor.rs`](../examples/rust/apps/modal_editor.rs)
|
|
1151
1175
|
|
|
1152
1176
|
### How do I tell the keypad from the main keys, or hear a lone Shift?
|
|
1153
1177
|
|
|
@@ -1420,8 +1444,10 @@ them sharing an edge show a hairline of the background through it.
|
|
|
1420
1444
|
`gradient` on the box: `gradient={{ to: 'bottom', stops: ['#1e2030',
|
|
1421
1445
|
'#14161e'] }}` runs to a side or a corner, `{ angle: 0.125, stops }` along
|
|
1422
1446
|
a direction in turns clockwise from east, and `{ radial: true, at: [0.5,
|
|
1423
|
-
0], stops }` out from a centre. A stop is a colour or `[colour, position]
|
|
1424
|
-
|
|
1447
|
+
0], stops }` out from a centre. A stop is a colour or `[colour, position]`,
|
|
1448
|
+
the colour a `$token` too; a token that misses is raised as
|
|
1449
|
+
`unknown-token` and its stop left out, so a two-stop gradient with a
|
|
1450
|
+
typo draws nothing over its `bg`. It paints over `bg` and under the border and the children, so a scrim is
|
|
1425
1451
|
a gradient with a transparent stop over whatever is beneath. The geometry
|
|
1426
1452
|
is the box's unit square stretched to the box — a corner is CSS's corner,
|
|
1427
1453
|
and an `angle` runs corner to corner at an eighth of a turn whatever the
|
package/index.d.ts
CHANGED
|
@@ -1890,6 +1890,8 @@ export type DoorCell = { is: string } | { as: string } | { no: string };
|
|
|
1890
1890
|
export interface Door {
|
|
1891
1891
|
rust: string;
|
|
1892
1892
|
c: DoorCell;
|
|
1893
|
+
/** The Odin binding's (packages/odin), pinned by its generator. */
|
|
1894
|
+
odin: DoorCell;
|
|
1893
1895
|
node: DoorCell;
|
|
1894
1896
|
lua: DoorCell;
|
|
1895
1897
|
doc: string;
|
|
@@ -2401,6 +2403,14 @@ export declare class Ctx {
|
|
|
2401
2403
|
* so a test can assert on it.
|
|
2402
2404
|
*/
|
|
2403
2405
|
optionAsAlt(): 'none' | 'left' | 'right' | 'both'
|
|
2406
|
+
/**
|
|
2407
|
+
* Whether the last frame asked for the platform's input method off
|
|
2408
|
+
* in its window (a root `<box imeOff>`) — no composition, and on a
|
|
2409
|
+
* Mac no dead keys and no press-and-hold; false when it did not.
|
|
2410
|
+
* `runWindowed` applies it to the window on change; a bare `Ctx`
|
|
2411
|
+
* hands the ask back so a test can assert on it.
|
|
2412
|
+
*/
|
|
2413
|
+
imeOff(): boolean
|
|
2404
2414
|
/**
|
|
2405
2415
|
* A headless context is one window, the main: this answers whether
|
|
2406
2416
|
* `window` names it (`"main"`, `0`, or left out) and addresses
|
|
@@ -2471,8 +2481,10 @@ export declare class Ctx {
|
|
|
2471
2481
|
* — whose first choice on macOS is the system's proportional
|
|
2472
2482
|
* face. Ids from `addFont` / `addSystemFont` / `loadFontFile`;
|
|
2473
2483
|
* one that names no font is left out, and `[]` is the
|
|
2474
|
-
* platform's list alone.
|
|
2475
|
-
* the
|
|
2484
|
+
* platform's list alone. `mono` text asks them straight after
|
|
2485
|
+
* its own face, ahead of the machine's other monospaced faces.
|
|
2486
|
+
* A new list shapes every text again; the same list twice is
|
|
2487
|
+
* nothing.
|
|
2476
2488
|
*/
|
|
2477
2489
|
setFallbackFonts(ids: Array<string>): void
|
|
2478
2490
|
removeFont(id: string): void
|
|
@@ -3653,8 +3665,10 @@ export declare class KuiWindow {
|
|
|
3653
3665
|
* — whose first choice on macOS is the system's proportional
|
|
3654
3666
|
* face. Ids from `addFont` / `addSystemFont` / `loadFontFile`;
|
|
3655
3667
|
* one that names no font is left out, and `[]` is the
|
|
3656
|
-
* platform's list alone.
|
|
3657
|
-
* the
|
|
3668
|
+
* platform's list alone. `mono` text asks them straight after
|
|
3669
|
+
* its own face, ahead of the machine's other monospaced faces.
|
|
3670
|
+
* A new list shapes every text again; the same list twice is
|
|
3671
|
+
* nothing.
|
|
3658
3672
|
*/
|
|
3659
3673
|
setFallbackFonts(ids: Array<string>): void
|
|
3660
3674
|
removeFont(id: string): void
|