From edf1192629be0978ed5e572bc119b7fa942fbe8f Mon Sep 17 00:00:00 2001 From: Adam Malczewski Date: Mon, 15 Jun 2026 20:04:22 +0900 Subject: docs: record screenshot + wallpaper decisions (plan §2, glossary, tasks) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - notes/plan.md §2: three settled-decision rows (screencopy/xdg-output in kernel; stb_image arbitrary-image decode + absolute-path fix; native ext-wallpaper + input_transparent flag + bundled default). - GLOSSARY: canonical 'wallpaper' term (user-confirmed). - tasks.md: 'just landed' milestone for screenshots + wallpaper. --- GLOSSARY.md | 6 ++++++ notes/plan.md | 3 +++ tasks.md | 18 ++++++++++++++++++ 3 files changed, 27 insertions(+) diff --git a/GLOSSARY.md b/GLOSSARY.md index bc8e555..da161ba 100644 --- a/GLOSSARY.md +++ b/GLOSSARY.md @@ -71,6 +71,12 @@ | **restore** | Return a minimized toplevel to the normal layer at its prior geometry and focus it; its preview leaves the dock. | unminimize, unhide | | **reveal** | The proportional, finger-following show/hide of the stage dock driven by the edge swipe (fraction 0..1); release snaps fully open or closed. | slide, animate (bare) | +## Wallpaper (ext-wallpaper) + +| Term | Meaning | Aliases to avoid | +|---|---|---| +| **wallpaper** | The desktop background image, composited in the `background` scene layer below every window by ext-wallpaper (standard tier). Config-driven (`[wallpaper]` in `unbox.toml`: `path`/`fit`/`color`), hot-reloaded; an input-transparent ui surface; falls back to a bundled default image when no `path` is set. | background (bare), desktop background, backdrop | + ## Workflow | Term | Meaning | Aliases to avoid | diff --git a/notes/plan.md b/notes/plan.md index 6e1d824..ed74877 100644 --- a/notes/plan.md +++ b/notes/plan.md @@ -68,6 +68,9 @@ solves), and the trigger that would reopen it. | **VT switching (Ctrl+Alt+Fn) is kernel-hardwired** before the key_filter (`wlr_session_change_vt`) | It is the session escape hatch — must work even if an extension throws or greedily consumes keys; not a rebindable feature (user decision) | — | | **Stage dock** (ext-stage-dock, standard) = the Stage-Manager-style left-edge dock of minimized-window **previews**, revealed by a left-edge **swipe**. **Fork B**: previews are toplevel snapshots imported as textures INTO the ui substrate's RMLUi context and shown as `` in ONE RML document | Closest to the iPad Stage Manager north star; one ui surface animates as a unit via RCSS; reuses the slice-3 dmabuf/EGLImage bridge in reverse (wlr pixels → RMLUi texture) instead of two-layer scene/RML lockstep | Cross-context texture import proves infeasible on crocus → fall back to Fork A (previews as `wlr_scene` snapshot nodes) | | **Mechanism in kernel/core, policy in ext-stage-dock.** Kernel ui substrate gains: preview-snapshot, list/container bindings, a gesture-CLAIM input path. ext-xdg-shell gains: `Toplevel::hide()/show()` (≠ unmap), `geometry()`, `scene_tree()`. ext-stage-dock owns: the "minimized" set, dock layout, gesture recognition, easing | Keeps "kernel names no feature" — snapshot/claim/list-bindings are generic primitives; minimize-to-dock is the only policy and lives in one standard extension | — | +| **Screenshot capability = `wlr-screencopy-v1` + `xdg-output-v1` globals created in the KERNEL** (user decision) | They are policy-free Wayland plumbing (wlroots wires them to the kernel-owned outputs/renderer), exactly like the existing compositor/subcompositor/data-device globals — so they pattern with those, not with shell extensions. `grim` works against them; the final image is the standard `wlr_scene_output_commit` composite (RML documents are scene-buffer nodes, captured correctly). The kernel still names no feature | A capture path needs compositor-side POLICY (e.g. interactive region UI) → that policy moves to an extension, globals stay in kernel | +| **Substrate decodes arbitrary raster images via vendored `stb_image`** (user-approved dep) — `` and `decorator: image()` load PNG/JPEG/BMP/GIF/TGA from any absolute path | The RMLUi render interface previously decoded ONLY uncompressed TGA; a desktop needs real wallpapers + (later) favicons. stb_image is single-header public-domain, no system package; warnings isolated to its own TU. A SubstrateSystemInterface JoinPath override keeps absolute paths from being slash-stripped during RmlUi URL resolution | A heavier codec need (animated/SVG) appears → add a real decoder dep | +| **Wallpaper = native config-driven `ext-wallpaper` (standard tier)** showing `[wallpaper]` image in the `background` scene layer; bundled default image (`assets/ext-wallpaper/default.jpg`) when none configured. Needs the kernel's new **`UiSurfaceSpec::input_transparent`** flag (a full-screen background ui surface must NOT steal clicks — the substrate's press-ownership is a per-rect, pre-bus test) | Native (vs requiring swaybg) fits the unbox config+RCSS+hot-reload idiom and the RML-compositing "wallpaper is an RML element" direction; input_transparent is the long-anticipated passthrough primitive (also unblocks the dock drag-out). swaybg still works too (ext-layer-shell background band) | Multi-output (one image per output) wanted → extend ext-wallpaper + an output-enumeration/box API | | **RML compositing (ADOPTED — Phase 0 spike PASSED GO on real Haswell+crocus; supersedes the compositing half of row 51).** RMLUi is the CONTENT compositor: toplevels, layer-shell clients (incl. wallpaper), and UI chrome are all RMLUi elements backed by LIVE, SHARED GL textures (zero per-frame copy via the existing shared EGLDisplay). Layout/animation/3D effects are RCSS. wlroots stays the foundation + plane manager (backend/output/renderer/seat, hardware cursor plane, fullscreen-video scanout bypass). Lost wlr_scene damage/scanout is mitigated by OUR dirty-gated rendering (idle ≈ no work) + damage-limited compositing + a deferred fullscreen scanout bypass. **Contract decision (user): RCSS is the single source of truth for ALL layout + animation; C++/extensions DRIVE the document through a TYPED substrate API but never own placement geometry directly — the typed-symbol rule governs cross-extension dependency discovery, not the RCSS styling vocabulary.** Spike report: `reports/rml-compositing-spike.md`; Phase-1 design: `notes/rml-compositing-phase1.md` | The appeal is Hyprland-grade window effects via DECLARATIVE RCSS (layout, transitions, 3D transforms, blur/shaders) with hot-reload — and RmlUi already does transform-aware hit-testing + RTT/filters, while slice 3 + the stage dock already proved dmabuf/EGLImage texture handoff on this exact crocus HW. Doing windows in RMLUi means tiling/effects/stage-manager are all RCSS policy on top. **Phase 0 proved on the real CF-AX3 GPU class: zero-copy live import, RCSS 3D transform on live pixels, input accurate through the transform, per-subsurface surface trees, idle dirty-gate, FBO→dmabuf present; ~30fps under a 4-window load, fill-bound (~10–15ms whole-output composite) with damage limiting as the known recovery** | A Phase-2 implementation blocker on the real seat (perf regresses below budget after damage limiting + scanout bypass, or the RCSS-only contract proves unworkable for a real tiling/effects extension) → fall back to wlr_scene compositing + transient snapshot-through-RMLUi effects | ## 3. Architecture diff --git a/tasks.md b/tasks.md index 22ef29e..72b60fe 100644 --- a/tasks.md +++ b/tasks.md @@ -5,6 +5,24 @@ ## Now +**Just landed — screenshots + wallpaper (user-driven, real-seat/nested VERIFIED):** +- **Screenshots (grim):** kernel creates `wlr_screencopy_manager_v1` + + `wlr_xdg_output_manager_v1` (policy-free plumbing, like data-device). grim + captures the standard `wlr_scene_output_commit` composite (RML docs are + scene-buffer nodes → captured). Verified nested: `grim` → valid 1280×720 PNG. +- **Arbitrary image decode:** vendored `stb_image` (user-approved); substrate + `LoadTexture` now decodes PNG/JPEG/… (was TGA-only), and a SubstrateSystemInterface + `JoinPath` override stops RmlUi stripping the leading `/` of an absolute path, so + `decorator: image('/abs')` AND `` both load. Kernel ui_pixel tests. +- **`ext-wallpaper` (NEW, standard tier):** `[wallpaper]` in unbox.toml + (path/fit/color), shown in the `background` layer, hot-reloaded (drop+recreate + inline doc); bundled default `assets/ext-wallpaper/default.jpg` when no path set. + Needed a new kernel **`UiSurfaceSpec::input_transparent`** flag (a full-screen + background surface must not steal clicks — substrate press-ownership is per-rect, + pre-bus). Verified nested: configured image + bundled default both render; input + passes through. swaybg (layer-shell) still works too. GAP: multi-output (primary + only). Commits on feat/rml-compositing. + **ACTIVE (core, user-driven) — Slice 13: RML COMPOSITING (Phase 0 GO → Phase 2 impl).** Big direction change: RMLUi becomes the content compositor — toplevels + layer-shell (incl. wallpaper) + chrome are RML elements backed by LIVE, SHARED GL textures, with -- cgit v1.2.3