Repository navigation
Existing Rust GUI apps on ToyOS: iced on one winit backend, paced redraws, forks on one branch per base - #528
Conversation
Work in progress on the branch; the pull request body is the record. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014iqcj4jDKpaiDX8B7CMvmK
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014iqcj4jDKpaiDX8B7CMvmK
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014iqcj4jDKpaiDX8B7CMvmK
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014iqcj4jDKpaiDX8B7CMvmK
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014iqcj4jDKpaiDX8B7CMvmK
The committed-files table moved to src/licence.rs with a licence column; the
four Open Sans rows follow it as Terms::Font("OFL-1.1"), and each new NOTICE
section carries its SPDX line.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014iqcj4jDKpaiDX8B7CMvmK
Review of #528 at 4ad645aReady for review: Net lines (
Fork heads were checked against the body: winit 6767a595/d857ac16, softbuffer 41ad75f, fontdb 2e445cf, memmap2 eb6cce2, wgpu 6aafc3a9, the repins as listed, fontique and slint through BLOCKER
NOTE
REMOVE
SEND BACK |
Owner ruling: the platform supports iced alone for now. The slint and egui test apps, the slint and parley/fontique forks and their `[patch]` rows are gone, and an issue records the choice with its exit. winit: the 0.31 fork line is retired and snake, calc and doom run on the 0.30 backend iced uses, so one ToyOS winit backend exists. On it, a redraw asked for after `pre_present_notify` waits for the window's frame event; a dropped window's redraws are forgotten; creating a window wakes nothing, and redrawing or dropping one wakes the loop only from another thread. The wake pipe is `toyos::wake` (`Waker` and `Bell`) beside `Poller`, and `window::Waiter`, logd's bell and soundd's line writer use it; `toyos` 0.13 -> 0.14. mio's waker could not take it as a swap and is filed. Forks: one branch per upstream base, with each fix appended; every fork names the SDK crates by a range, so the tree's patched version answers it and an SDK bump owes no fork a commit. `sdkversion::judge` refuses a lockfile holding two versions of a published crate. getrandom 0.2/0.3 and libloading keep a second branch until the toolchain re-locks (filed). memmap2 refuses `make_exec`; wgpu names its native platforms once. The compositor counts each window's presents and frame events and says both when it closes the window. Tests: toolkit_iced proves its label is Open Sans at 16 px by correlating the panel with the word rendered here by fontdue, and bounds its idle presents; toolkit_winit_loop drives the loop through winit's API (a proxy event from AboutToWait, cross-thread events, redraws and drops, a drop in the creating handler, a kept closed window); toolkit_winit_pace holds an animation to the frame events; window_wake watches four windows. The OFL text ships beside the fonts. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014iqcj4jDKpaiDX8B7CMvmK
iced's counter example leaves the userland workspace for tests/iced-counter, a package with its own lock and patches that toolkit_iced builds and carries into the toolkit desktop. No image and no userland resolve pays for iced's tree any more (wgpu, fontdb and memmap2 leave userland's patches and 2334 lines leave its lock), and upstream's it_counts, a test of iced's own simulator, joins no host lane. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014iqcj4jDKpaiDX8B7CMvmK
Each of the counter's two labels must correlate with the word as Open Sans draws it at 16 px. With no system fonts iced draws its buttons flat and "Increment" correlated at 0.349 at best; a gradient in place of the widgets reached 0.156; the labels at head reach 0.787 and 0.866. The bar is 0.6. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014iqcj4jDKpaiDX8B7CMvmK
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014iqcj4jDKpaiDX8B7CMvmK
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014iqcj4jDKpaiDX8B7CMvmK
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014iqcj4jDKpaiDX8B7CMvmK
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014iqcj4jDKpaiDX8B7CMvmK
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014iqcj4jDKpaiDX8B7CMvmK
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014iqcj4jDKpaiDX8B7CMvmK
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014iqcj4jDKpaiDX8B7CMvmK
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014iqcj4jDKpaiDX8B7CMvmK
Answer to the review of 4ad645a — head 42059f5Under the owner's ruling of 2026-09-26 (iced only, for now). Every mutation below was a checked patch, shown to build (no BLOCKERs
NOTEs
REMOVEAll five: the Linux host-lane sentence and the Gates
Left for the owner: deleting the six per-SDK branches the previous head minted (each contained in its base branch, consumed by nothing) was refused by this session's permissions. |
Review of #528, round 2, at 42059f5Ready for review: Net lines (
Round-1 BLOCKERs
BLOCKER
NOTE
REMOVE
SEND BACK |
…Arch64 The rust pin moves to 4874af48e26 (on toyos-inbox): the aarch64-unknown-toyos target spec, and std's `_start` and TLS descriptor resolver on AArch64 (variant I, `__toyos_tlsdesc_dynamic`). It is a compiler change, so this worktree builds its own compiler (src/compiler.rs) and the primary's is untouched. - The build: `GUEST_TARGETS` gains aarch64-unknown-toyos, and every architecture has a userland, so `USERLAND_ARCHS` and the plan's `Userland` switch (whose `Absent` arm nothing could reach any more, and whose `without_userland` nothing called) are deleted. `cargo run -- --arch aarch64 --build-only` builds std, libtoyos_c and the userland for AArch64 and puts them on ROOT. - libc: `_start`, memcpy/memmove/memset and the square roots move into `userland/libc/src/arch/`, one module per architecture, and gain their AArch64 versions (pair loads and stores with a byte tail, fsqrt). The copies were checked on this AArch64 host against its own copy_within/fill over 360,000 cases (lengths 0..300, offsets 0..20, overlapping both ways); a copy_backward whose chunk test was 8 instead of 16 died on the same check (SIGBUS, exit 138). - toyos-window's and metalprobe's scanout drain moves into an arch module (SFENCE; DSB ST on AArch64), and the ARCH_RULES rows for them and for libc become module places. toyos-window is published, so it bumps to 0.16.0: 0.15.0 is taken by #525 and #528. - calc, snake and doom are left off an AArch64 ROOT, by name at build time (`NOT_YET_BUILT`): softbuffer's and winit's toyos forks resolve the published toyos-window 0.2.0, whose framebuffer is x86-64 only (issues/build/the-toolkit-forks-resolve-an-x86-only-toyos-window.md). Everything else in the userland workspace, and toyos-ld and toyos-cc as guest programs, builds and links for AArch64. compiler.rs keys a compiler on the content of its sources alone: keying on the git spelling of compiler/ made committing what had been built as local changes a new compiler and a full rebuild. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014iqcj4jDKpaiDX8B7CMvmK
…guard
The winit loop test fails on any event delivered for a window after its
application dropped it, other than its one `Destroyed`, in every stage. Stage
4 ends at the second `AboutToWait` after its `Destroyed`, with the iteration
between forced by `ControlFlow::Poll`, since that iteration is where a window
still queued for creation got its `Resized` and `RedrawRequested`. A new stage
5 asks a window for a redraw and drops it in a `user_event`, which runs after
the loop's destroy step, so only `Window::drop`'s own `forget` keeps the
redraw from reaching it. The harness then reads the compositor's close lines:
every window the app dropped has to be closed "by the client itself" before
the window it kept is closed by GUI+Q, which a window leaked until the app's
exit is not.
`a_system_font_ships_as_it_is_and_the_console_font_as_its_raster` takes its
scratch from `toyos_tmpdir::TempDir` rather than building one from
`temp_dir()` and leaking it on a panic. `every_host_scratch_is_the_guard`
refuses `temp_dir()` in host code outside three counted exceptions: the guard
itself, the keymap golden's dump, which is left for its reader on purpose,
and `src/release.rs`, filed.
The slint/egui entry is a deferral by the owner ("for now"), so its kind is
`defect` and it stays open, as `issues/README.md` rules for a deferral.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014iqcj4jDKpaiDX8B7CMvmK
…ept one's A window the app still held when it left is closed by its exit, and that close says "by the client itself" too. Read up to the kept window's GUI+Q close, which comes before the exit, a leaked window is still open. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014iqcj4jDKpaiDX8B7CMvmK
Upstream's `it_counts` is a `#[cfg(test)]` no lane builds, so its dev-dependency locked nom, png, sha2 and iced_selector for nothing. The example's source stays byte for byte. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014iqcj4jDKpaiDX8B7CMvmK
Pins `toyos-0.30.13` at f58e1f3b. `Window::drop` takes the window out of the loop's creation queue, so one created and dropped in a handler that runs after the loop's creation step, a `Destroyed` handler among them, closes its compositor window at the drop and hears only its `Destroyed`; before, the loop took it in its next iteration, delivered `Resized` and `RedrawRequested` after the `Destroyed`, and kept it open until the app left. A window dropped in the handler of one of its own polled events hears none of the rest, and a `Resized` queues its redraw before the handler runs, so a drop inside it forgets that too. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014iqcj4jDKpaiDX8B7CMvmK
… is asked over ssh The review of 1b8d459 found four blockers and a fast-tier question. HOME on the direct path. std's direct spawn handed a child the parent's whole environment, so an ssh exec of an undeclared binary ran with HOME=/state/sshd. init now answers a launch of an undeclared program with the session's HOME (MSG_NOT_DECLARED carries it; toyos::launch's Outcome::NotDeclared has it), and std's direct spawn carries only a HOME its caller named or init answered, never its own (fork commit 957f1426, merged with toyos-inbox at 7a809b75, #520's pin, in 80ea645f). The layout, asked over the cable. layout_fresh_boot boots tests/layoutcase (sshdcase plus a declared shell and the locale applet) with a staged key, then over ssh: `shell -c 'echo $HOME'` must print /home/toy (a launched row's HOME is init's, over sshd's); `locale de` and an interactive shell write /config/keyboard-layout and the shell's history; and test_rs_layout_paths, declared nowhere so sshd spawns it directly, asserts its HOME, both files by literal path, and the exact listings of /home/toy and /state. An empty directory is listed. Vfs::list names the directories the VFS carries in created_dirs, so an empty dot-folder is in its parent's listing and the dotfile walk sees it. The filed DATA-directory issue loses that bullet and its slug says what is left. Also: a manifest row that serves a port and is not marked a service is refused at render, and every config is rendered by a host test; init's folder failure no longer says the whole session home is missing; the shell's history finds its own folder whether HOME is the session's or, at stage 2, the folder itself; the track records the owner's rulings, gains a time-zone, a language and a fonts stage, and no longer ships JetBrains Mono here, which leaves src/assets.rs and NOTICE to #528; the sshd fail-closed issue is closed, its exit met by the blank DATA volume every image-less boot gets. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014iqcj4jDKpaiDX8B7CMvmK
`toolkit_iced` matched each label at its best place anywhere in the window,
and "Increment"'s best was on "Decrement": at 0.787 at (486, 279) against
"Decrement"'s 0.866 at (479, 279), so the check passed on one word's ink.
The label matched best now claims its place and the other is matched only
away from it: "Increment" then scores 0.781 on its own button, and with a
view of only `button("Decrement")` it scores 0.349 and the test reds. The
launch goes through `toolkit_launch`, which now takes the line to type.
`toolkit_window_wake` ends with one wait after more wakes than the wake pipe
holds, measured on a fresh pipe (2 097 088 bytes here): a wake that finds
the pipe full is one already pending, and the flood is one wake to the wait
and one take.
`toolkit_winit_loop`'s idle stage allows one iteration, the deadline's. The
second it allowed, a `WaitCancelled` straight after the close, was the
window leaked by stage 4: instrumented, that wait watched only the leaked
window and its completion was that window's, and with the leak fixed twelve
runs saw none.
The toolchain's memmap2 branch still answers `Ok` from `make_exec`, filed:
appending the fix there leaves `rust/Cargo.lock` behind it.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014iqcj4jDKpaiDX8B7CMvmK
#525 took toyos-abi 0.13.0, toyos 0.14.0 and toyos-window 0.15.0, the same toyos and toyos-window versions this branch had taken. toyos-abi stays at #525's 0.13.0; toyos moves to 0.15.0 and toyos-window to 0.16.0, its `toyos` pin with it. Every tracked lockfile is re-locked on the merged manifests, which also takes #525's locks off the old fork branches: none holds a second version of toyos-abi, toyos or toyos-window. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014iqcj4jDKpaiDX8B7CMvmK
Round 3: the answer to the review, at 254ea74BLOCKER 1, zombie window: fixed.
BLOCKER 2, surviving
BLOCKER 3, second temp-dir helper: fixed.
NOTEs
REMOVE: all three lines are deleted. ABI.
Gates
|
# Conflicts: # tests/toyos-rust-tests/Cargo.lock # userland/Cargo.lock
…sions Merging origin/main (#531) collided this branch's toyos/wake.rs and toyos-window/wait.rs additions with main's own bump of the same two crates to identical version numbers (0.15.0, 0.16.0) for different content. Move both one minor past main's landed pins and re-lock every tracked workspace with `cargo update -w`, which also drains the dead winit 0.31.0-beta.2 subgraph and the stale getrandom/mio/socket2 fork pins the split-version gate (added on this branch before the merge) then caught: real crates.io toyos/toyos-abi 0.1.0/0.2.0 resolving beside the tree's own path versions because those pins predated the tree's `-sdk-0.12` branch renames and the getrandom `toyos-0.4` branch fix already at its head. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014iqcj4jDKpaiDX8B7CMvmK
`git checkout --theirs` on the two conflicted Cargo.lock files also staged `rust` from whatever the submodule's on-disk checkout happened to be, which was still this branch's pre-merge commit rather than the auto-merged one — silently reverting main's HOME/launch ABI follow-through in `sys/process/toyos.rs` and breaking every std build. Fast-forward the gitlink to main's pin instead. `tests/toolkitcase/system.toml`'s `compositor` row predates main's rule that a program serving a machine-wide port is marked a service by hand (`ServesWithoutService`); every other desktop config already carries `service = true` beside it. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014iqcj4jDKpaiDX8B7CMvmK
Follows through on the previous commit's description: main's ServesWithoutService rule reds every config whose machine-wide-serving program isn't marked `service = true` by hand, and this file's `compositor` row was the one left behind. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014iqcj4jDKpaiDX8B7CMvmK
Merge main (#531) and re-syncHead is now Versions
What the re-lock and the gates caught (all pre-existing, surfaced by the merge)
Fast-tier A/B — skipped
Gates
Not arming auto-merge or waiting on CI, per the brief. 🤖 Generated with Claude Code |
|
Round-3 BLOCKERs closed and judged at 254ea74 (zombie window purged from creates, forget pinned, host scratch through TempDir, each red under its mutation); final round 4026950 merges #531 and takes toyos 0.16.0 / toyos-window 0.17.0, re-locks onto the range branches (--check-forks 0, abi-split 0), and restores main's rust gitlink after a merge slip. --ci host 43/43 and toolkit_ 4/4 exit 0. The fast-tier A/B was skipped for disk; the extra wide reds were a different three each run, each green alone and each covered by an existing filed issue, none on a GUI path. Landing. |
#528 (e4e540d) published toyos 0.16.0 and toyos-window 0.17.0 for the iced/ winit work, the same versions this branch had already set for its own ABI change, so the two collide on crates.io. toyos-abi 0.15.0 is still free (main never moved it past 0.14.0), so it stays; toyos moves to 0.17.0 and toyos-window to 0.18.0, past main's landed versions, with every in-tree pin and lockfile re-locked behind them (`cargo update -w` in toyos/, userland/, userland/libc/, tests/toyos-rust-tests/ and tests/iced-counter/ — the five workspaces a tracked lockfile of theirs names toyos or toyos-window). Conflicts, each the two branches' additions side by side: - src/build.rs: `ALL_CONFIGS` gained `tests/toolkitcase/system.toml` (main) and `tests/updatecase/system.toml` (this branch); both kept, alphabetical. - tests/toyos-rust-tests/Cargo.lock, userland/Cargo.lock: re-locked rather than resolved by hand, so `swap`/`update` (this branch's new programs) and main's iced/winit additions both land, and the stale `toyos-abi` 0.1.0/ 0.2.0 registry entries main's fork-pin fix retired stay gone. `rust`'s gitlink is unchanged (`git ls-tree HEAD rust` still names 80ea645f, main's own) — this branch never moved it. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014iqcj4jDKpaiDX8B7CMvmK
…528) Conflicts, each resolved to carry both sides: - bootloader/src/main.rs: the boot map's ROOT_* names with #530's update imports. - src/image.rs: main's slotted layout, with `arch` threaded into create_boot_image and create_esp_volume for the removable loader's path. - src/build.rs: main's Parts, shipped_parts and signing, keyed per architecture: loader_key takes the arch, the embedded key and the floor scope; root_image_key the plan (config and arch) and the key; build() writes image_for(plan.arch). - tests/common/qemu.rs: a test's own firmware variables file where it names one, and otherwise the architecture's pflash. - toyos-window is 0.19.0, past main's 0.18.0, since its scanout drain moved into arch modules here; both lockfiles take main's and that version. - tests/common/update.rs names the x86-64 plan and image. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014iqcj4jDKpaiDX8B7CMvmK
#528's tests/iced-counter locks the path toyos-window, which the merge moved past main's 0.18.0. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014iqcj4jDKpaiDX8B7CMvmK
main landed #528 (iced, `toyos::wake`) and #530 (self-update), which took toyos-abi 0.15.0, toyos 0.17.0 and toyos-window 0.18.0. - SDK versions: past main's, to toyos-abi 0.16.0, toyos 0.18.0 and toyos-window 0.19.0; every tracked lockfile re-locked in its own workspace with `cargo update -w`, tests/iced-counter's among them. - toyos/src/lib.rs: both `power` (this branch) and `wake` (main). - userland/logd/src/main.rs: main's hunks move logd's `Own`/`Theirs` bell onto `toyos::wake`; this branch deleted that machinery (logd's own lines are records in its ring), so they have nothing to land on and this side is kept. `toyos::wake` stays for its other users. - userland/soundd/src/say.rs: deleted here; main's hunk moves its wake pipe onto `toyos::wake`, and soundd's mix thread writes a lane here instead. - rust: main's pin is still 80ea645f83b, which this branch's pin already merges. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014iqcj4jDKpaiDX8B7CMvmK
…, #531, #534) into the Netstack3 netd Two conflicts. tests/common/origin.rs: main added `volumes` to the imports this branch had split to name `segment`'s NEIGHBOUR and NEIGHBOUR_MAC; both kept. userland/Cargo.lock: main's lock taken whole and re-locked against this branch's manifests (`cargo metadata`), which adds the mirrored crates and their dependencies and drops smoltcp and its defmt. The rust gitlink fast-forwarded to main's fbf6ad143d8; this branch's pin (7a809b7591f) is its ancestor, and the branch made no fork commit of its own. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014iqcj4jDKpaiDX8B7CMvmK
Stage 1 of
issues/design-debt/toyos-has-a-desktop.md, the platform, under the owner's ruling of 2026-09-26 that the platform carries iced only, for now. An unmodified iced app opens a window under the real compositor, draws its text in a system font, presents only what it has to, and leaves with code 0 when the compositor closes it. snake, calc and doom move to the same winit backend.What changed, per decision
iced only. The slint and egui test apps, the slint and parley/fontique forks, and their 16
[patch]rows are gone.issues/design-debt/slint-and-egui-are-not-supported-by-the-owners-choice.mdrecords the choice, with the exit "revisit once the Rust target is upstream". The ruling says "for now", so it is a deferral: the entry iskind: defect,status: open, asissues/README.mdrules for a deferral. This also settles the review's slint-default-features BLOCKER, since slint is not supported.One ToyOS winit backend. snake, calc and doom are ported to winit 0.30:
can_create_surfacesbecomesresumed, andSurfaceResizedbecomesResized.CursorMoved/CursorLeft/MouseInput, with the position kept from the last move.The tree pins only
ToyOSOrg/winittoyos-0.30.13. Nothing pins the 0.31 line any more (winit-toyos, +1249 over its tag asmainpins it).On that backend (winit
toyos-0.30.13at f58e1f3b, +1246/−1 over v0.30.13):pre_present_notifyis held until the window's next frame event. One asked without it goes at once. iced callspre_present_notifybefore every present, soRedrawRequest::NextFrameand any animation run at the compositor's rate.Window::droptakes the window out of the loop's creation queue. Take a window created and dropped in a handler that runs after the loop's creation step, aDestroyedhandler for example. Its compositor window now closes at the drop, and it hears only itsDestroyed. Before, it gotResizedandRedrawRequestedafter itsDestroyed, and its compositor window stayed open until the app left.Resizedqueues its redraw before the handler runs, so a drop inside the handler forgets that redraw too.EventLoopProxy::send_eventalways wakes.The wake pipe is the SDK's.
toyos::wake(Waker,Bell) sits besidePoller.window::Waiterholds aBelland hands outArc<Waker>.SDK versions, after #525. #525 took toyos-abi 0.13.0, toyos 0.14.0 and toyos-window 0.15.0. The last two were this branch's versions. This branch merged
origin/mainand moved on:toyospin.Every tracked lockfile is re-locked on the merged manifests.
tests/iced-counteris among them.The compositor counts. Each window's close line gives its
MSG_PRESENTs and theMSG_FRAMEs sent back (… presents=P frames=F). The tests below judge by that line.Forks: one branch per upstream base, SDK crates by range.
toyos-abi,toyosandtoyos-windowas>=<first version whose API it uses>, <1.[patch.crates-io]'s path answers that range at whatever version the tree is on. Measured: a patch at 0.11.0 is chosen over the registry's 0.12.0 for>=0.10, <1.sdkversion::judge(theabi-splitlane and--pr) refuses any tracked lockfile holding two versions of aPUBLISHEDcrate.On the merge:
main's locks after Storage stage 3, steps 1–4: toyos-blockring, SYS_DEVICE_DMA_MAP, blockd and partition sessions #525 held registry toyos-abi 0.1.0 and 0.2.0, toyos 0.1.0 and 0.2.0, and toyos-window 0.2.0. They came in through cpaltoyos-0.18.0-sdk-0.2, softbuffertoyos-0.4.8-sdk-0.2, winittoyos-0.31.0-beta.2-sdk-0.2, getrandomtoyos-0.2/toyos-0.3and libloadingtoyos.userland/Cargo.lockandtests/toyos-rust-tests/Cargo.lock.getrandom 0.2/0.3 and libloading keep their
-sdk-0.12branch beside the base branch.rust/Cargo.lockpins the base branch one commit back, and fast-forwarding it would put the toolchain behind in--check-forks(filed, with the exit).memmap2 (
toyos-0.9.11):make_execanswersUnsupported, asmap_execdoes. The fix is not on thetoyosbranch the toolchain pins:rust/Cargo.lock(87ae85a1) one commit behind, which--check-forksreports;rust/Cargo.lockchanges the compiler's own dependency graph.Filed as
issues/build/the-toolchains-memmap2-branch-answers-ok-from-make-exec.md. Nothing in the toolchain callsmake_exec, andrustc_data_structuresgates ToyOS away from memmap2.wgpu (
toyos-27.0.4, +10/−3): the native Vulkan/GL platform set is one alias, andvulkan,glesandtarget_has_backendare written in terms of it. The prepared upstream branch does the same for trunk's three sets (Vulkan, DRM, GL).The OFL ships.
assets/fonts/OFL.txtmoved fromlicenses/with the same digest and has its ownCOMMITTED_FILESrow. It ships beside the fonts as/system/share/fonts/ofl.txt, andNOTICEsays so instead of claiming the name table is the licence.One scratch helper.
a_system_font_ships_as_it_is_and_the_console_font_as_its_rastertakes atoyos_tmpdir::TempDir.sourcegate::every_host_scratch_is_the_guardrefusestemp_dir()in host code outside three counted exceptions:src/release.rs, filed.iced's app is a package of its own.
tests/iced-counterholds upstream'sexamples/counter/src/main.rsbyte for byte, assrc/bin/iced-counter.rs, with its own lock and patches.toolkit_icedbuilds it and carries it into the toolkit desktop.userland/resolve pays for iced's tree. userland no longer patches wgpu, fontdb or memmap2.iced_testdev-dependency is gone, so upstream'sit_countsis never built.Tests
The four
toolkit_tests are Nightly, intests/toolkitcase.toolkit_icedassets/fonts/OpenSans-Regular.ttfat 16 px and matched by normalised cross-correlation. The label that matches best claims its place, and the other is matched only away from that place. Each needs ≥ 0.6.toolkit_launch, which takes the line to type.toolkit_winit_pace: an animation draws 60 frames (pre_present_notify, present, thenrequest_redrawinsideRedrawRequested). The compositor must count all 60 presents, and no more than frames + 1.toolkit_winit_loopruns through winit's API. The app fails on any event delivered for a window after the app dropped it, other than its oneDestroyed. The stages:AboutToWaitwith no window open.Destroyedhandler. The stage ends at the secondAboutToWaitafter itsDestroyed; the iteration in between is forced byControlFlow::Poll.user_event.The harness then reads the compositor's close lines up to the kept window's GUI+Q close. Every window the app dropped (22) has to be closed "by the client itself" before that line.
toolkit_window_wakeAlso:
memmap_exec_refused(shared boot);assets::tests::the_system_fonts_ship_with_their_licence;sdkversion'sa_lockfile_holding_two_versions_of_a_published_crate_is_refused_by_name;sourcegate::every_host_scratch_is_the_guard.Negative controls
Each one is a checked patch, shown to build, run, and reverted, and the tree is clean after each. Winit mutations are commits on scratch branches of a local clone, consumed as
file://git sources. The head arm of each is the same clone at f58e1f3b, the commit pushed, and it is EXIT=0.Round 3, at this branch's heads 2d0739e…254ea746:
Window::dropleavescreatesalone (the fix's one line deleted)--nightly toolkit_winit_loop--nightly toolkit_winit_loopforget(BLOCKER 2)self.redraws.lock().unwrap().forget(self.id);deleted fromWindow::drop--nightly toolkit_winit_loopsrc/assets.rs's fix reverted tostd::env::temp_dir()cargo test --lib every_host_scratch_is_the_guard …left: {"src/assets.rs": 1, …}wake'sWouldBlockErr(SyscallError::WouldBlock)dropped fromWaker::wake'sOkarm--nightly toolkit_window_waketoyos/src/wake.rs:32, wide and alonecolumn![button("Decrement")…]only--nightly toolkit_icedWithout the disjoint rule, "Increment"'s best place at head was on "Decrement": 0.787 at (486, 279) against "Decrement"'s 0.866 at (479, 279). Away from it, on its own button, "Increment" scores 0.781.
The unexplained idle wake, measured. I instrumented
window::Waiterto name each completion's handle and ran the test withIDLE_WAKES = 1:WaitCancelledstraight after the close came in 2 of 6 runs. In each, the wait watched only the leaked stage-4 window, and the completion was that window's. It was not a leftover registration.So
IDLE_WAKESis now 1, and the allowance is gone.Rounds 1–2, measured at 42059f5 or earlier and not re-run:
Event::Frame => { r.frame(id); r.request(id); }(a frame event redraws)--nightly toolkit_icedpre_present_notifydoes nothing--nightly toolkit_winit_pacetake_wake()moved afterAboutToWait--nightly toolkit_winit_loopWindow::dropdeleted--nightly toolkit_winit_looprequest_redrawdeleted--nightly toolkit_winit_loop.filter(|live| !live.closed)deleted--nightly toolkit_winit_looplet _ = watched;--nightly toolkit_window_wakePoller: … capacity is 4panic atpoller.rs:269make_execmake_exec→Ok(())-- memmap_exec_refusedadd_dirskips.txtcargo test --lib the_system_fonts_ship_with_their_licencee05f79d(namestoyos-abi = "0.1")--ci abi-splitsrc/assets.rs:let system_font = false;--nightly toolkit_iced--nightly toolkit_icedIndependent oracles:
pre_present_notifydocumentation describes it.Gates (exit codes), at 254ea74 (merged with
origin/mainat 7345e3f, #525)cargo run -- --ci host→ EXIT=0, "Host: 43 step(s), all green", including "nothing left in $TMPDIR".cargo run -- --ci abi-split→ EXIT=0, "bumped: toyos 0.14.0 -> 0.15.0, toyos-window 0.15.0 -> 0.16.0".cargo run -- --check-forks→ EXIT=0, "23 branches asked, all current".cargo test --test toyos-build -- --nightly toolkit_→ EXIT=0, 4 of 4.-- --nightly desktop_window_child→ EXIT=0. It PASSes, quarantined and green.-- --nightly doom_→ EXIT=0.doom_musicPASSes;doom_sound_floodPASSes, quarantined and green.cargo test --test toyos-build→ EXIT=1: 395 passed, 4 failed. Each is settled below.The fast tier was run twice on the head and once on
main, in the same session.Head, first run. EXIT=1: 395 passed, 4 failed.
lan_mdns_answerfails on "path must be shorter than SUN_LEN", wide and alone. That ismain's defect, filed.handle_kill_policyandhandle_transferfail on aSharedMemcensus one over. Both are ALONE GREEN.partition_claim_gives_upfails twice, on two different assertions.Head, second run. EXIT=1: 395 passed, 4 failed.
lan_mdns_answer, the same as above.partition_claim_departure,quiesce_wakes_on_the_last_parkandmetal_job_rebootfail. Each is ALONE GREEN.main(7345e3f), full fast tier. EXIT=1: 397 passed, 1 failed. The failure islan_mdns_answer, with the same message.Each of the four first-run reds, alone, on both sides.
partition_claim_gives_upEXIT=0,handle_kill_policyEXIT=0,handle_transferEXIT=0,lan_mdns_answerEXIT=1.main: the same four exits, in the same order.--known-red: NO for every one of these excepthandle_transfer, whose row does not cover the census message.The wide-only reds are filed as beside-other-guests defects:
issues/boot-media/partition-claim-gives-up-reds-beside-other-guests-and-is-green-alone.mdissues/boot-media/partition-claim-departure-told-no-flush-beside-other-guests.mdissues/build/quiesce-wakes-on-the-last-park-lost-its-serial-ready-beside-other-guests.mdissues/build/metal-job-reboot-drained-no-kernel-output-beside-other-guests.mdhandle_kill_policy's andhandle_transfer's census reds are the classissues/kernel/deferred-release-outlives-its-syscall.mdnames, which citeshandle_kill_policy.What I cannot rule out. Two wide head runs had three non-
lanreds each, a different three each time. The one widemainrun had none. That is a difference between the two sides, and I have not shown it to be noise. Nothing in this diff touches shared memory, block storage or the quiesce path. The runtime code every boot runs that this branch changes is logd's wake, nowtoyos::wake, and soundd's.What I am unsure of
toolkit_window_wake's 30 s quiet bound (which the harness scales by host speed). A much slower host could meet that bound first; I have not measured one.pump_eventswith a finite timeout is compiled but not exercised: every client here enters throughrun.[profile.toyos]is not shared. Cargo reads a profile only from a workspace root or from a config, so sharing it means moving every copy (root, kernel, bootloader, userland, toyos-rust-tests and its four TLS crates, iced-counter) into one--configthatsrc/build.rspasses. That is a build-system change past this brief.Filed
issues/build/the-release-path-stages-in-tmpdir-outside-the-scratch-guard.md(tooling)issues/build/the-toolchains-memmap2-branch-answers-ok-from-make-exec.md(defect)issues/design-debt/slint-and-egui-are-not-supported-by-the-owners-choice.md(defect: the deferral)issues/build/the-toolchain-pins-an-older-commit-of-three-userland-forks.md(tooling)issues/design-debt/mio-s-toyos-waker-never-drains-its-pipe.md(finding)issues/design-debt/toyos-ships-no-monospace-or-serif-system-font.md(finding)issues/build/a-lane-s-tap-socket-path-outgrows-sun-len-on-the-dev-host.md(defect,main's: the fast tier'slan_mdns_answerred)issues/build/metal-job-reboot-drained-no-kernel-output-beside-other-guests.mdissues/design-debt/softbuffer-reads-a-toyos-window-behind-its-lock.mdissues/build/fork-tier-crates-still-pin-toyos-abi-at-0.1.mdissues/build/an-sdk-bump-leaves-every-fork-on-the-last-sdk.mdissues/design-debt/a-toyos-winit-window-redraws-unpaced.mdFork branches (consumed)
toyos-0.30.13toyos-0.4.8toyos-27.0.4toyos-0.23.0toyos-0.9.11toyos-0.18.0toyos-0.2-sdk-0.12,toyos-0.3-sdk-0.12,toyos-0.4toyostoyostoyos-sdk-0.12Nothing consumes the per-SDK branches the previous heads minted:
toyos-0.30.13-sdk-0.15;toyos-0.4.8-sdk-0.15;toyos-0.18.0-sdk-0.13;toyos-0.4-sdk-0.12;toyos-sdk-0.13.The owner can delete them.
main's-sdk-0.2branches stay until #530 has merged.Prepared upstream branches (none opened)
add-toyos-system-fonts(+7)/system/share/fonts.instance-no-backend-target(+14/−4 on trunk)forks.toml).Net lines (
git diff --shortstat origin/main...HEAD)56 files, +7681/−642. About +540/−95 of that is production and manifests, +1330/−3 tests, +5489/−481 lockfiles, and +322/−63 records.
🤖 Generated with Claude Code
https://claude.ai/code/session_014iqcj4jDKpaiDX8B7CMvmK