Repository navigation
The desktop and its own clients draw at the display's scale, set live on a display port (scale, item 1) - #931
Conversation
…a display port #895 chose a scale from the panel's EDID and nothing drew at it. This is the rest of the scale as #895's accepted design says it. - The window protocol carries the scale as its own wire type, `window::Scale`, n/120 from 1 to 4, with the one rounding every party converts with: half away from zero, a rectangle by its corners. `WindowInfo` and `ResizeInfo` carry it, a client refuses one outside the range, and a window asked for in logical pixels is converted by the compositor (`window::Size`). `Event::Resized` means the size or the scale changed. - The compositor's `display` port, held by `toybox` alone for `screen`: the mode and the scale, read and set. `screen scale 1.25|auto` relays every window at the new scale and is kept in the compositor's HOME; a scale no quarter step, or one leaving less than the least screen, is refused by name, and a kept scale a mode cannot hold is drawn held down and stays kept. `MSG_SET_RESOLUTION`, `MSG_GET_RESOLUTION` and `MSG_RESOLUTION_CHANGED` leave the window protocol; a mode on GOP is refused by name. - The compositor draws its chrome, text, icons and cursor at the scale: `Chrome` at a scale, the font rasterized from the TTF at the scaled cell (`toyos-font`, the build's rasterizer moved in, so build and guest share one producer and the 8x16 raster is byte-identical), and the icons and cursor drawn from their SVGs at the scaled edge (`toyos-icon`, which `build/icons.rs`, `sprite` and `files`' copy fold into; the build still refuses an SVG past the subset). The hardware cursor carries the sprite up to 64 pixels, 3.2x, and the hot spot is the shape's own, scaled. - A window keeps the buffer it last presented until its first present into the new one (`toyos_desktop::Buffers`), so a relay never flashes; the window budget counts two buffers per window. `toyos_desktop::relayout` scales a normal window's rectangle by its corners and retargets a maximized or snapped one. - terminal, filepicker and its consent prompt, and `files` draw at their window's scale; editor and paint stay at 1, as #895's ruling has it. - The winit fork's ToyOS backend answers `scale_factor()` with the window's scale and sends `ScaleFactorChanged` before `Resized` (ToyOSOrg/winit `toyos-0.30.13` at 48c7022a). - An image starts the desktop at a scale where the panel gives none with the compositor row's `scale=N` (`cargo run -- --scale 2`), since QEMU's firmware publishes no EDID. The desktop font ships as its TTF beside its raster, with its OFL text, and the icons as their SVGs with their MIT notice. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016UzbDnM9m6nQWhbjGi6Lv1
…s without A published SDK crate depends on the SDK's own crates alone, which is what `sdkversion`'s offline resolution of the forks' requirements holds, and `toyos-window` reaches every winit app. `ttf` is on for the desktop's programs and the build, and `toyos-window` takes the raster's drawing without it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016UzbDnM9m6nQWhbjGi6Lv1
One conflict: lib/manifest's module list, `device` beside `display`. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016UzbDnM9m6nQWhbjGi6Lv1
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016UzbDnM9m6nQWhbjGi6Lv1
toyos-desktop depends on toyos-window for the wire scale, so the host's clippy shapes lint toyos-window as a dependency of a host member: `is_multiple_of` in both scales, and toyos-window's own `Waiter::default` and `is_empty`. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016UzbDnM9m6nQWhbjGi6Lv1
#925 moved virtio-gpu into the compositor behind `Display`. Kept both: - One layout for a mode and a scale: #925's `relayout(mode)` and this branch's `lay_out(scale)` are `lay_out(mode, scale)`, which `change_mode`'s flip, a display event and the display port's `screen scale` all take. A display event's panel scale is the base where no scale is kept or named by the image, so a host window's resize changes the mode and, only then, the panel's scale. - The display port's `screen WxH` takes #925's flip through `mode::follow`; a display that keeps the firmware's mode refuses it as `NoModes` (`Display::sets_modes`). `MSG_SET_RESOLUTION` stays gone. - `Display::set_cursor` takes the hot spot; the cursor is the display's where it has a plane and the sprite fits 64 pixels, emptied otherwise. - `mode::LEAST` is built from `TEXT_CELL`, and `Scale`'s least screen is it. - clipboardcase's compositor serves `display` beside #925's claim. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016UzbDnM9m6nQWhbjGi6Lv1
Review of #931 at
|
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016UzbDnM9m6nQWhbjGi6Lv1
…des the swap, one buffer outstanding - B1: a relay at a larger scale fits a normal window's content, and where a maximized or snapped one goes back to, to the work area (`Chrome::fit`), so no frame passes the screen and the budget's bound holds. - B2: `WindowInfo` and `ResizeInfo` carry the buffer's generation, and `MSG_PRESENT` carries it back (`window::PresentRect`); the compositor shows the given buffer only on a present of its generation, so a present drawn into the old buffer after a resize keeps the old one shown. A generation the window never held drops the client by name. - B3: while a given buffer is unpresented no other is given; the window is owed it, and given it at the present that swaps, so a window holds two buffers and no more, a hung client included. - B4: the issue records what is left with owner and exit: virtio-gpu at a scale read by log alone, editor and paint, calc and snake at 1. - B5: a logical request whose frame would pass the work area is fitted to it and said (`toyos_desktop::requested`), not refused; a physical one is still refused past the screen. - R1: a clippy shape for `toyos-font` with `ttf` off. - S3: the virtio boot's compositor starts at `scale=2`, held to 1.75 and then 1.5 across the host's resize. S1: toyos-desktop takes toyos-font without `ttf`. S2: a kept scale not read is said. S6: `gop_edid_scale` names a bench's kept scale. S8: `--scale` beside `--boot-config` is refused by name. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016UzbDnM9m6nQWhbjGi6Lv1
Re-review of #931 at
|
|
Bench readings at the round-1 head |
The desktop and its own clients draw at the display's scale, which
screen scalesets live: item 1 ofissues/the-desktop-draws-at-the-panels-scale.md, "the rest of the scale" of #895's accepted design. #895 chose 1.5 for both benches' panels and nothing drew at it.At scale 2 on a 1920x1080 panel, from the new guest row:
What changes
window::Scale(sdk/window/src/scale.rs): n/120 from 1 to 4, Wayland fractional-scale-v1's denominator. The one rounding is decided there and documented at the top of that file: half away from zero, in integers, a rectangle by its corners (round_ratio; the compositor's chrome, relayout and cursor hot spot, the terminal's scrollbar and the clients all convert through it).WindowInfoandResizeInfocarry the scale; a client refuses one outside 1..4 as a protocol error. A window is asked for aswindow::Size::{Any, Logical, Physical}; a logical size is converted by the compositor at the output's scale. Input coordinates and damage stay in the window's physical pixels.Event::Resizedmeans the size or the scale changed.displayport (window::display), served by the compositor and received bytoyboxalone (build/build.rs'sHELD_ALONE): the mode and the scale, read and set; one request per connection, answered with the state or a named refusal.screen,screen WxH,screen scale 1.25|auto. A scale that is not a quarter step, or that leaves less than the least screen (642x446 logical), is refused by name; a set scale is kept in the compositor'sHOME(/state/compositor/scale) and a kept scale a later mode cannot hold is drawn held down, said, and kept.MSG_SET_RESOLUTION,MSG_GET_RESOLUTIONandMSG_RESOLUTION_CHANGEDleave the window protocol; a mode set on GOP is refused by name (NoModes).Chrome::scaledandDesk::new(screen, scale, apps); text from the TTF at the scaled cell; the title-bar icons and the cursor from their SVGs at the scaled edge; the hardware cursor while the sprite is at most 64 pixels (3.2x), software past it. Every window is relaid on a change (toyos_desktop::relayout: a normal window's rectangle scales by its corners and is fitted so its frame stays inside the work area, a maximized or snapped one is retargeted and where it goes back to fitted the same way) and given a buffer at the new scale. A logical request whose frame would pass the work area is fitted to it and said (toyos_desktop::requested), as winit's requested size is a request: doom's 960x600 logical at scale 2 on 1920x1080 opens fitted where it would otherwise be refused; a physical request past the screen is still refused.WindowInfoandResizeInfogive each buffer a generation, whichMSG_PRESENTcarries back (window::PresentRect). A window is shown from the buffer it last presented until a present carries the given buffer's generation, so a present drawn into the old buffer after a resize keeps the old one shown; a generation the window never held drops the client by name. While a given buffer is unpresented no other is given: the window is owed it and given it at the present that swaps (toyos_desktop::Buffers), so a hung client holds two, and the budget counts two per window.toyos-fontgainsFont::from_ttf, the build'srasterize_cellsmoved in, so the build's 8x16 raster and a guest's raster at any cell are one function; the shipped 8x16 raster is byte-identical to the build's before the move (sha25641f922af…both).toyos-icon(sdk/icon) isbuild/icons.rsmoved, with a mask at any edge and a safe blend;spriteandfiles' copy fold into it, which closesissues/sprite-dereferences-a-raw-pointer-behind-a-safe-fn.md. Its transcendental functions arelibm's, so host and guest draw the same pixels; the resvg-compared digest of the shipped icons is unchanged. The build ships the SVGs and still refuses one past the subset by parsing it with the crate.filesdraw at their window's scale and follow a change; editor and paint stay at 1, as The loader hands the panel's EDID to the compositor, which chooses the display's scale #895's ruling has it; console stays at 1.toyos-0.30.13gains48c7022a:scale_factor()answers the window's scale, a resize whose scale changed sendsScaleFactorChangedthenResized, and a requestedSizegoes on the wire as the kind it is.Cargo.lockpins it.share/licenses/; the icons ship as their SVGs with their MIT notice (NOTICEupdated).Decisions for the orchestrator
scale=N, not a kernel parameter. The brief suggestedscale=2on the kernel parameter line. Userland has no channel to that line today, and the kernel parameter line is in the image's signed header, so it is no more boot-time than ROOT; the virtio path (virtio-gpu leaves the kernel: the compositor drives it through its claim and follows the host's display #925) takes no framebuffer claim, soFramebufferInfocannot carry it either. The row argument needs no kernel or ABI change:tests/images/scalecase.tomlwritesargs = ["scale=2"], andcargo run -- --scale 2adds it to the compositor's row (build::at_scale; the name istoyos_manifest::display::SCALE_ARG). The build cannot ask a macOS host's backing scale without a host-only tool, so the flag is documented inREADME.mdrather than defaulted. Precedence: a keptscreen scalechoice, then the image's argument, then the panel's EDID.toyos-desktopdepends ontoyos-windowfor the wire scale and its rounding, so the rounding has one home; it uses types only.toyos-font's rasterizer is its defaultttffeature, whichtoyos-windowturns off: a published SDK crate depends on the SDK alone (sdkversion's offline resolution holds that), andtoyos-windowreaches every winit app.Checks
Review round 1 at head
cdd9fd3f1(main335927b83merged), evidencepr-931atf437f090:--ci hostexit 0, 86 steps green, with a clippy shape fortoyos-fontwithoutttf(log);--build-onlyexit 0; the guest rows below plus the virtio row, now booting atscale=2(1280x800 drawn at 1.75, 1024x768 followed at 1.5), exit 0, 5 of 5 (log); new controls each red their tests: relay unfitted (B1), swap on any generation (B2), never owe (B3), logical request not fitted (B5) (log); the guest controls rerun (log); the 8x16 raster compared with main's producer, identical (log). Both benches PASSgop_edid_scaleatc849397d3(T14 handle 0, AMD handle 1, panel 1.5, a 200x100 window drawn 300x150; readbacks); the row is restaged atcdd9fd3f1since B1 and B2 change the relay it exercises.The first round's checks, at head
c849397d3(mainbd5d4e0c0, #925, merged); evidencepr-931atccdb6eb3:cargo run -- --ci host, exit 0, 86 steps green (log). New host tests: the wire scale's range, decimal parsing and refusals, rounding at the halves and at negative coordinates, touching rectangles at every quarter step, the cell, title bar and icon at 1, 1.5 and 2 (sdk/window/src/scale.rs); the display port's requests, an absurd scale as no request, payloads of another length, state and refusals on the wire (display.rs);Sizeon the wire; the policy scale (quarter steps, the least screen, a kept scale held down and kept); chrome at a scale, relayout across 1→2→1 and 1→1.5→1 (at most a pixel's drift) and onto the work area with maximized windows; the two-buffer swap; two buffers in the budget; the cursor hot spot and the hardware plane's 64-pixel edge; text cells at each scale and a larger cell rasterized at its size rather than doubled; an icon at twice the edge drawn at its size; the mask's clipped blend.cargo run -- --build-only, exit 0 (log).cargo test --test toyos-build -- a_window_is_drawn_at_the_scale_and_relaid_at_the_next desktop_without_x2apic screen_fatal_halt_composited the_opening_exchange_with_qemus_agent_completes the_compositor_drives_the_virtio_gpu, exit 0, 5 of 5 (log).window_refusal(a shared-boot member the harness cannot filter, with two new absurd-scale cases) through a scratch-only machine row onscalecase, reverted: PASS (log).a_window_is_drawn_at_the_scale_and_relaid_at_the_next(tests/images/scalecase.toml,Profile::Metal's q35 with a 1920x1080 GOP panel and the i8042): claim — a client's window asked for as 200x100 logical is on the panel 400x200 under a 56-row title bar at scale 2, andscreen scale 1, run by the client through the launcher astoybox, relays it to 200x100 under 28 rows. Read off QMP screendumps by the fill's extent; the host presses Enter (ps2server) once it has read each panel. Why a guest: what reaches the panel is the compositor's buffer swap, chrome and the protocol's scale meeting on a running desktop; no metal machine's glass can be read. Screens.gop_edid_scalenow also holds, onmetalcase's existing boot,compositor: drawing at scale 1.5andscale_window's 200x100 logical window drawn 300x150 at 1.5, on both benches, and names a bench's kept scale if it finds one. Staged withcargo test --test toyos-build -- --metal --metal-readback <dir> gop_edid_scale(exit 2, staged, log); not yet run on either bench.a_half_rounds_away_from_zero; one buffer in the budget reds its test; a swap that never swaps, a hot spot at the corner, a relayout that keeps the physical rectangle and a display port that reads an absurd scale as auto each red theirs; the compositor ignoring the logical flag stalls the scale row at "the window at 2" (it drew 200x100 at 2); no relay at all stalls it at "relaid at 1"; a client taking an absurd scale redswindow_refusal. One mutation passed and was investigated: dropping only therescaled ||clause leaves the row green, because a scale change changes every normal window's size and so relays it anyway; the clause keeps a window whose size survives a rescale told its scale.Risks and what is left
lay_out(mode, scale); a display event's panel scale is the base where no scale is kept or named by the image, so a host window's resize changes the mode and the panel's scale only. On virtio-gpu the scale is read by log alone (the virtio row atscale=2); no screendump measures a window there, nor the hardware cursor's hot spot, norscreen WxHover the port — recorded in the issue with its exit.PhysicalSizeon every host), recorded in the issue with owner and exit; a third-party app that ignoresscale_factor()draws small (no compositor upscaling, by design).screen scalewrites the kept file in the compositor's loop (review S5, not taken: one small write per person's choice).filesand the compositor read the font and icons from/system/share, a path only this tree has (issues/five-apps-read-the-system-font-by-a-path-only-this-tree-has.md, updated).🤖 Generated with Claude Code
https://claude.ai/code/session_016UzbDnM9m6nQWhbjGi6Lv1