v0.22.1
Bug-fix release for scroll-blit idle short-circuits, LastDirtyRegions idle-frame semantics, and regression coverage for negative sub-pixel and nested scroll.
Added
- Regression tests for negative sub-pixel and nested scroll (
src/widget/render_system.rs): three-frame -0.4 accumulation pinning residue against an explicitly-computed Q24.8 reference, plus a HiDPI viewport variant covering that the walker quantises in logical-pixel space regardless of physical scale. Nested scroll gains a pixel-equivalence test that applies inner + outer shifts in DFS post-order and checks every output row matches a fresh full-repaint of the composed source mapping.
Changed
App::render_dirtywritesLastDirtyRegions::default()on idle frames (src/app.rs): idle frames previously skipped the resource write, leaving the resource at whatever the last non-idle frame published. Consumers that read it as "shifts produced last frame" — notably the cursor feedback short-circuit gate added in this release — would otherwise see a stale shift signal forever, defeating the gate's optimisation once any scroll happened. The resource now consistently means "plan from the most recently completed frame".
Fixed
cursor_feedback_systemshort-circuit recomputes when layout shifts under a static pointer (src/feedback/cursor.rs): the pointer-unchanged short-circuit returned early on cached(x, y, down)even when entities under the cursor had moved between frames. A magnetic-rect overlay therefore froze on the previous target's rect when scroll-blit shifted children below. Newworld_has_layout_motiongate bypasses the short-circuit when the previous frame published anyRegionShift(viaLastDirtyRegions) or any entity carries pendingScrollDelta. Both signals are O(1) on hash-indexed storages.lazy_list_systemclears stale slot bindings on shrink and over-sized pools (src/components/lazy_list.rs): the idle short-circuit (visible_start unchanged, all targets bound) skipped cleanup, so two cases left slots painting wrong content —pool_size > item_countat startup (slots beyonditem_countnever bound and never hidden) anditem_countshrinking under live bindings (slots whose binding now points past the live tail). Newclear_extra_slotssweep runs before the idle short-circuit;apply_bindingsremovesHiddenfrom slots it reuses when the data set grows back.