summaryrefslogtreecommitdiffhomepage
AgeCommit message (Collapse)Author
2026-06-13Slice 10 c2/d1 fix: dock previews were blank (RML/RCSS authoring bugs)Adam Malczewski
Real-seat (nested) showed the dock compositing but slots blank. Three bugs in the inline dock document, all caught in the live RmlUi log: - <img src="{{ row.preview }}"> never bound — RmlUi interpolates {{ }} only in TEXT, not attributes, so it tried to load a texture literally named "{{ row.preview }}". Fixed with data-attr-src="row.preview". - font-family: sans-serif -> "No font face defined" (substrate only loads Noto Sans). Fixed to the loaded face. - transform-origin: top left -> RCSS parse error. Fixed to RmlUi-valid syntax. Verified real-seat: minimizing two foot windows shows two preview cards in the dock with the actual window snapshots visible; the live log is free of the three [rmlui] errors. Super+M works repeatedly with >1 window ("works once" was the single-window no-op: nothing left to focus/minimize). Suites green build + asan.
2026-06-13tasks: slice 10 a1-d1 landed (stage dock); real-seat + 1 boundary call nextAdam Malczewski
2026-06-13Slice 10 d1: RCSS animation — dock slide-in + per-slot settleAdam Malczewski
Layers animation on c2's static pipeline with zero data-model / contract change (c2 glue test passes unchanged). The dock body slides in from the left edge on empty->non-empty via an RCSS transition on transform:translateX driven by a bound `open` bool (data-class-open); slide-out defers set_visible(false) until the slide's transitionend so the close is seen. Each freshly instanced preview card plays a one-shot @keyframes (scale 0.72->1.0 + fade, transform-origin top-left = "scales down into a spot"). Dock stays a 240px left-edge strip (animation is a transform inside the surface, never a resize) so windows stay clickable. Key finding: RmlUi 6.2 dispatches animationend/transitionend as real events, and the substrate's data-event-* path binds a listener for ANY registered event — so data-event-transitionend routes into bind_event with NO kernel change. The ONLY remaining gap for the literal cross-screen window->dock flight is a single input-transparent UiSurfaceSpec flag (a kernel boundary decision, NOT built). Restore stays instant in d1 (animated grow-back is e1's drag-out). 10/10 suites green on build + build-asan (asan clean). Visual feel is real-seat.
2026-06-13Slice 10 c2: stage dock end-to-end (minimize -> preview -> restore)Adam Malczewski
ext-stage-dock activate() now wires the full static pipeline: track toplevels via the ext-xdg-shell Service; Super+M (stopgap keybinding) minimizes the focused window -> snapshot a Preview from its scene_tree(), push a slot, hide() the live node, refocus another window; the dock is one overlay UiSurface rendering the slots via the b2 list bindings (data-for over {preview src, title}); tapping a slot fires bind_list_event -> show()+focus() the window and drop its slot/Preview. Storing the Toplevel* across minimize is safe because hide() keeps it mapped; slots are dropped on on_toplevel_unmapped. Teardown is reverse-declaration-order (subscriptions first, surface before slots), asan-clean. host-bin installs ext-stage-dock (standard, depends_on xdg-shell; hidden until it holds a minimized window). Headless glue test (real in-process xdg client) proves the model + scene-node enable bit true->false->true, slots 0->1->0. RML carries dock/slot classes as d1's RCSS animation hooks. Stopgaps: Super+M (to migrate into an ext-keybindings action + a stage-dock Service post-d1); favicon deferred (needs an XDG icon-theme dep — to surface to the user). 10/10 suites green on build + build-asan. Visual/tap path is real-seat (pending).
2026-06-13Slice 10 b4: ext-stage-dock new unit — skeleton + pure coresAdam Malczewski
New standard extension (id "stage-dock", depends_on xdg-shell). Ships the unit skeleton (factory-only public header, minimal no-op activate, meson + suite) and the two PURE DECISION CORES, doctest-hard with no kernel/wlroots: - src/reveal.hpp: reversible left-edge swipe recognizer (stream -> reveal fraction [0,1]; release -> open/close commit by threshold + fling velocity). - src/dock_layout.hpp: reveal-fraction -> on-screen dock box (slides -dock_width .. 0) + slot capacity / content-height / per-slot rect math. Real wiring (RML doc, snapshot, minimize/restore) lands in c2/d1/e1. Root meson.build gains the subdir; host-bin registration deferred to c2. ext-stage-dock suite green (17 cases / 74 assertions). Edits in packages/ext-stage-dock/ + root meson.build subdir.
2026-06-13Slice 10 b1: ext-xdg-shell Toplevel minimize mechanismAdam Malczewski
Neutral compositor-side mechanism the stage dock drives to minimize a window (the "minimized" state/policy stays in ext-stage-dock). Adds to Toplevel: geometry() -> wlr_box (size the preview + restore position), scene_tree() -> wlr_scene_tree* (feed UiSubstrate::create_preview + the node hide/show toggles), and hide()/show() — disable/enable the scene node so the client stops compositing and frame callbacks WITHOUT unmapping (no on_toplevel_unmapped, no focus change), idempotent. Verified against wlroots 0.20 that a disabled node quiesces frames. A real in-process wayland client test (test_minimize.cpp) drives it on the headless backend. ext-xdg-shell suite green on build + build-asan. Edits confined to packages/ext-xdg-shell/.
2026-06-13Slice 10 b2: UiSurface list/container data bindingsAdam Malczewski
The stage dock is one RML document rendering a variable list of slots (one per minimized window). Adds the deferred slice-6 list-binding shape to UiSurface: bind_list(name, count) + typed per-row fields bind_list_string/int/double/bool (list, field, getter(row)) read as {{ row.field }} via data-for, and bind_list_event(list, event, callback(row)) routed from data-event-*(it_index). dirty(<list>) re-reads count + visible rows. Same error-isolation + bind-before- first-frame contract as the scalar bindings; nested lists unsupported. kernel suite green on build + build-asan (asan clean). Edits confined to packages/kernel/.
2026-06-13Slice 10 a1: preview pipeline spike — wlr pixels -> RMLUi texture (Fork-B GO)Adam Malczewski
The keystone for the stage dock. Proves Fork B on the real target (Mesa crocus, HD 4400): a toplevel's pixels, rendered by the wlr GLES2 renderer into a LINEAR ARGB8888 dmabuf, import as an EGLImage -> sampled GL texture in the sibling RMLUi GLES 3.2 context (the slice-3 bridge run in reverse) and composite into an <img src="unbox-preview://N"> inside a ui surface — upright, color-correct. Public surface (ui.hpp): class Preview (source_uri/source_width/source_height/ refresh) + UiSubstrate::create_preview(wlr_scene_tree*) -> unique_ptr<Preview> (nullptr if no GL path; never throws). Kernel-suite probes: ui_preview_import_is_dmabuf, ui_pixel(x,y). Clean four-resource teardown (URI reg, GL texture, EGLImage, dmabuf); refresh-after-source-destruction is UB (consumer drops Preview on unmap). kernel 42 cases/150 assertions green on build + build-asan (asan clean, no new suppressions). Edits confined to packages/kernel/.
2026-06-13Stage dock: land plan + vocabulary (Fork B, mechanism/policy split)Adam Malczewski
Slice 10 (stage dock): Stage-Manager-style left-edge dock of minimized-window previews revealed by a left-edge swipe. Records the Fork-B decision (previews are toplevel snapshots imported as textures into the RMLUi context, shown as <img> in one RML document) and the mechanism/policy split (kernel: snapshot + list bindings + gesture-claim; ext-xdg-shell: hide/show/geometry/scene_tree; ext-stage-dock: minimized set, layout, recognition, easing). Adds canonical terms: stage dock, stage (reserved), preview, favicon, gesture, swipe, minimize, restore, reveal.
2026-06-13docs: record kernel-hardwired VT switching (plan §2, tasks)Adam Malczewski
2026-06-13Kernel: Ctrl+Alt+F1..F12 VT switching (session escape hatch)Adam Malczewski
Intercept the XF86Switch_VT_1..12 keysyms before the keybinding filter and call wlr_session_change_vt, so the user can always switch consoles while unbox runs. Clean no-op without a session (headless/nested). Pure vt_for_keysym helper + doctest; wlroots reached via the wlr.hpp wrapper. Real-seat verified on the CF-AX3.
2026-06-13Slice 5b: config-driven keybindings — Super→fuzzel, Alt+Tab; kernel ↵Adam Malczewski
exports WAYLAND_DISPLAY ext-keybindings (new core ext) reads unbox.toml: tap-Super spawns fuzzel, Alt+Tab/Alt+Shift+Tab rotate focus across all toplevels, plus Alt+F1 and Ctrl+Alt+Backspace (quit). ext-xdg-shell's hardcoded keybinds removed (migrated to the toml). Kernel setenv()s WAYLAND_DISPLAY at startup so extension-spawned clients connect to unbox, not the launching session — fixes fuzzel "no monitors" on the real seat. build + build-asan green: third-party Mesa/EGL/DRM + vendored-RmlUi sanitizer noise suppressed (suppressions/), our code stays leak-checked; a real libwayland leak in the layer-shell client test fixed. Harness: spawn-env + sanitizer-noise rules, diagnose-real-seat skill, GLOSSARY keybinding/action/tap-binding. Real-seat verified on the CF-AX3.
2026-06-13Slice 5: real ui substrate + unified input routing + touch-mode; spike retiredAdam Malczewski
The ui substrate is now the extension-facing contract (unbox/kernel/ui.hpp): Host::ui() -> UiSubstrate::create_surface(spec) -> UiSurface with typed scalar bindings (int/double/bool/string getters), data-event callbacks (error-isolated per extension), dirty(), geometry/visibility — RMLUi and GL stay kernel-private. Production sync: glFinish replaced by EGL_KHR_fence_sync + 2-deep wlr_swapchain. ui_spike retired (orientation guard + dirty-cycle coverage live on as substrate tests). Input: ONE kernel routing path feeds pointer AND touch into ui surfaces with consume-or-pass semantics and implicit-grab ownership (the consumer of a press owns the matching release; per touch point too) — fixes drag-release-over-ui sticking. touch-mode: state machine + debounce + on_touch_mode_changed notification, NO visual scaling (user decision after hardware hands-on; dp-ratio stays 1.0; see plan §2). ext-xdg-shell: GrabMachine generalized to pointer-OR-touch interaction source (touch titlebar drag works; originating-point pinning); fixed the seat implicit-grab leak (suppressed release after forwarded press swallowed all later touch-downs — pointer/touch alternation doctested); factory renamed create(). ext-layer-shell: on_demand keyboard interactivity via scene hit resolution. host-bin: --ui-demo extension (temporary acceptance demo on the public contract, dies in slice 6). User hands-on verified: same surface by mouse and finger, tap counter, touch-mode neutrality, no click-through, drag alternation, fuzzel on_demand. 113 doctest cases green, ASan/UBSan clean (our code), idle RSS ≈78 MiB. Harness: UX-feel hands-on lesson (ORCHESTRATOR §2.6), nested-run pkill/setsid notes, touch-mode glossary redefinition.
2026-06-12Slice 4: extension host + typed bus; xdg-shell/layer-shell extracted to core ↵Adam Malczewski
extensions The kernel now names NO concrete feature. It owns: the extension host (install/topological activate, missing-dep/cycle = startup error), the typed Event/Filter bus (error-isolated: a throwing extension is disabled, never the session; RAII Subscriptions), the Host API (per-extension facade: borrows, scene layers, event catalogue, typed services), the public RAII Listener, and a typed surface→scene-tree registry (Host::host_surface/scene_tree_for) that replaced the untyped wlr_surface.data convention both extensions flagged. - ext-xdg-shell (core): toplevel/popup lifecycle, focus-on-map, click/tap-to-focus, pointer/touch routing incl. button+axis (the kernel only moves the cursor and emits — a contract-doc lie caught by user hands-on), interactive move/resize via pure GrabMachine (fixes the request-arrives-after-release race: grab requires request ∧ button-down, release always ends it), Alt+F1 cycle, Ctrl+Alt+Backspace terminate (labwc's default A-Escape=Exit killed the dev session once — never again; see nested-run skill). - ext-layer-shell (core): wlr-layer-shell v1 (proto v5) for external clients; pure doctest-hard arrangement core; fuzzel verified visually nested (fix: seed outputs from output_layout at activate — events-only tracking missed pre-activation outputs; plus a scene-node double-free). - First protocol codegen: vendored wlr-layer-shell XML + wayland-scanner server-header propagated through kernel_dep; wlr.hpp grew a namespace→_namespace keyword fix for the generated header. - Glossary: 'scene layer' (user-approved). New rules earned: parallel-wave-builds, contract-docs. - User hands-on verified: typing, click-to-focus, drag-select, scroll, titlebar drag-move (slow + flick), Alt+F1, fuzzel + arrows, touch tap, Ctrl+Alt+Backspace. 68 doctest cases green, ASan/UBSan clean (our code), idle RSS ≈73 MiB.
2026-06-12Harness: summon spikes/high-risk units with the opus agent (slice-3 lesson)Adam Malczewski
2026-06-12Slice 3: THE SPIKE — RMLUi→wlr_scene bridge lands, GOAdam Malczewski
Plan A verified on hardware (HD 4400/crocus): RMLUi renders into a GLES 3.2 sibling-context FBO backed by a dmabuf wlr_buffer (wlr_allocator + EGLImage import), composited as a wlr_scene_buffer with per-frame damage. Plan B (glReadPixels→shm) implemented and verified as runtime fallback; auto-engages when any Plan-A precondition fails. Plan C not needed. - Hello-world RML doc: text, data-bound frame counter, pointer input proof (hover/:active) — verified upright on screen via screenshot after fixing the classic FBO Y-flip (buffer-level V-flip keeps display == document coords for input); position-aware orientation guard added. - Temporary spike surface: Options::ui_spike + frame-count/orientation probes, host-bin --ui-spike flag; replaced by the real ui substrate contract in slice 4+. - kernel suite 6 cases / 416 assertions green; ASan/UBSan clean in our code (Mesa leak noise + 2 benign UBSan downcast reports inside vendored RMLUi are known); idle RSS ≈83 MiB. - Deferred (notes/plan.md §7): glFinish→EGL fence + swapchain; dmabuf render-format negotiation (private API in wlroots 0.20).
2026-06-12Slice 2: tinywl port — kernel compositor runs nested, manages toplevels, ↵Adam Malczewski
touch added Server contract (pimpl, create/run/dispatch/terminate) over a faithful tinywl 0.20.1 port: outputs via wlr_scene, xdg-shell toplevels+popups, focus, interactive move/resize, keyboard/pointer through wlr_cursor — plus touch (down/up/motion/cancel/frame via seat notifies with per-point origin tracking), which tinywl lacks. RAII Listener replaces manual wl_list_remove bookkeeping; shutdown ordering documented in kernel.md. xkbcommon added as a system dep. Verified: nested under labwc (output WL-1, foot mapped and focused on GLES2) and a headless+pixman boot test in the kernel suite.
2026-06-12Slice 1: Meson skeleton — kernel links wlroots 0.20 from C++, RMLUi 6.2 ↵Adam Malczewski
vendored Root meson.build (C++23, WLR_USE_UNSTABLE, ccache-detected) with RMLUi 6.2 as a wrap-file tarball built through the cmake module (no git submodules — settled decision) and doctest 2.5.2 from wrapdb. kernel unit: extern-"C" wlr.hpp wrapper (with the C99 [static N] array-param workaround documented in kernel.md), slice-1 probe contract, doctest suite (1/1 green). host-bin: composition root printing versions, exit 0. tasks.md slice 1 done.
2026-06-12Set up the agent harnessAdam Malczewski
Constitution (AGENTS.md), orchestrator workflow with the header-contract read rule and harness-growth duties (ORCHESTRATOR.md), wlroots-seeded glossary, 4 safety reflexes, owner-agent briefs, 3 skills, and the living plan (notes/plan.md) with hardware-verified facts, settled decisions, and the slice 1-9 roadmap (tasks.md). Slice 0 done; next: toolchain bootstrap.