summaryrefslogtreecommitdiffhomepage
path: root/assets
AgeCommit message (Collapse)Author
2026-06-15ext-wallpaper: config-driven desktop wallpaper (new standard-tier unit)Adam Malczewski
A new standard-tier extension that composites a desktop background in the 'background' scene layer, below every window. Reads [wallpaper] from unbox.toml (path / fit = cover|contain|stretch|center / color), hot-reloaded via watch_file (drop + recreate an inline RCSS document with the values baked in -- avoids fragile decorator data-binding). The surface is input_transparent so it never steals clicks. Pure doctested config core; factory-only contract. When no path is configured it falls back to a bundled default image (assets/ext-wallpaper/default.jpg, auto-installed to the data dir), resolved to an absolute path via $UNBOX_ASSET_DIR or the UNBOX_ASSET_DIR_DEFAULT compile define. Degrades gracefully (color-only) if there is no GL path or the file is missing. Sized to the primary output (multi-output is a documented gap). Wiring (composition root): root meson subdir, host-bin installs it unconditionally with the config path, unbox.toml gains a documented [wallpaper] sample. (swaybg via ext-layer-shell's background band keeps working too.)
2026-06-15ext-window-field(rml-compositing): floating windows + resize-to-tileAdam Malczewski
Floating windows: move (titlebar), resize (two bottom corner grips), and a per- window close button. Per-window geometry (x,y,w,h,z) is bound STATE applied via data-style left/top/width/height + z-index; a pure, doctested geometry core (move / resize_bl / resize_br with anchored-opposite-edge + min-size, field clamp) computes drag results. Positioning uses left/top (NOT a transform: RmlUi's data-style does not apply a transform here the way it does left/top/width/height, and a transform would also offset the drag hit-test). z-order raise on focus; cascade placement from the client's own size. Resize-to-tile: a frame-pumped feedback loop configures each client to its on- screen box (Toplevel::set_size) so the live texture maps 1:1. Policy is config- driven -- [window-field] resize_mode = off|settle|continuous|debounced in unbox.toml, hot-reloaded; pure doctested config core. Windows are shown via <img data-attr-src> (NOT an RCSS image() decorator) so the kernel's surface-element input-back, click-to-focus, popup placement and box readback -- all keyed off the <img> src -- work. host-bin passes the config path + --rml-compositing (the latter selecting server- side decorations) through to the extensions. tasks.md records the wave.
2026-06-15rml-compositing: make the window field actually render (2 real bugs)Adam Malczewski
Diagnosed live (nested unbox + grim screenshots). Two bugs stopped any window from showing; both fixed and visually confirmed (multi-window, live-updating, focus highlight, RCSS tiling). 1. kernel (ui_substrate.cpp, adopt_node) — STABLE TEXTURE ID across re-imports. The live import did glDeleteTextures+glGenTextures every commit, minting a NEW GL id each frame. But RmlUi's image()/<img> decorator caches the texture HANDLE it gets from LoadTexture(uri) ONCE, so after the first re-import it drew a DELETED texture -> blank. Now node.tex is allocated ONCE and just re-pointed at the new EGLImage (dmabuf) / re-uploaded (shm) on each re-import, destroying the previous EGLImage after the rebind. The id stays constant => RmlUi's cached handle stays valid => the window updates live. (Reimport counting unchanged.) 2. ext-window-field assets — the window texture is painted via an RCSS image() DECORATOR bound with data-style-decorator (the stage-dock pattern), NOT an <img src="{{ w.live_uri }}">: RmlUi does not substitute a data binding inside an img src, so the literal "{{ w.live_uri }}" was reaching the texture loader ("Could not load texture"). Also `contain` (was `cover`) so the whole window shows instead of cropping its center. Verified: foot composites as a surface element in the window field and updates live (a ticking clock); a 2nd window tiles with the focused one highlighted. kernel + ext-window-field suites green; build-asan kernel green (no leak/UB). Follow-up: a kernel regression test asserting the texture id is stable across re-imports (no test caught this — RmlUi caching is the subtlety).
2026-06-15ext-window-field(rml-compositing W3): toplevels as RCSS surface elementsAdam Malczewski
NEW core unit (id "window-field", depends_on "xdg-shell"), installed by host-bin ONLY under --rml-compositing / UNBOX_RML_COMPOSITING (default off; the classic wlr_scene path stays the default until RML compositing is signed off on hardware). It composites application toplevels as RCSS surface elements inside ONE ui surface (the window field) instead of as wlr_scene nodes: - activate(): fetch ext-xdg-shell Service (typed), create the window-field UiSurface at SceneLayer::normal sized to the primary output, subscribe to on_output_added + on_toplevel_mapped/unmapped/focused. - on map: Toplevel::wl_surface() -> UiSubstrate::create_surface_element(); the toplevel is Toplevel::hide()'d out of wlr_scene (the surface element is now the sole compositor of its pixels; the substrate drives its frame callbacks); appended to bind_list("wins") (live_uri = source_uri(), focused, title, app_id). - on unmap: drop the SurfaceElement + row. on focus: flip the focused flag. - Layout/animation are RCSS (assets/ext-window-field/field.{rml,rcss}): a wrapping flex field where the focused window dominates and the rest tile below, animated on a transition. No geometry from C++ (the user's contract decision). - Keyboard focus stays ext-xdg-shell's job; pointer/touch input-back is automatic in the kernel; this unit wires no seat calls. Wiring (orchestrator): root meson subdir, host-bin install behind the flag + ext_window_field_dep. Headless glue test (40 assertions): map tracks the window + drives hide(), 2nd map, focus flip via the Alt+Tab path, unmap removes it; no-GL degrade asserted. build + build-asan green; host-bin links; no regressions. Known gaps (change-requests): click-to-focus a BACKGROUND window needs a kernel "surface-element pressed -> notify owner" hook (next); wallpaper needs ext-layer-shell surface exposure (Wave 3b).
2026-06-14ext-stage-dock: C++-driven interruptible slide animationAdam Malczewski
RmlUi only starts a transition on a class/definition change, never on the inline data-style-transform the dock uses for slide, so keyboard/minimize/restore open-close had stopped animating (snapped). Own the animation in C++ instead: a pure SlideAnimator that every path flows through -- keyboard/minimize/restore play it, a touch drag scrubs it (pause + set position from the finger), and release resumes easing from the current position to the snap target. Duration + easing are read from the #panel RCSS 'transition' via transition_timing(), so they stay hot-reloadable and any named RmlUi tween works. Drives slide per frame via request_frames; the surface now hides when the close animation completes (replaces the old transitionend path). Body=drag-handle / panel=transform split preserved.
2026-06-14ext-stage-dock: use shader-based linear-gradient for the dock backgroundAdam Malczewski
horizontal-gradient is RmlUi's legacy decorator: it bakes the ramp into interpolated vertex colours through the plain colour shader, so it bypassed the gradient dither and showed hard 8-bit alpha banding over light backgrounds. Switch to linear-gradient(to right, ...), which renders per-pixel in our GL3 gradient shader (where the dither lives), giving a clean fade to transparent.
2026-06-14ext-stage-dock: interactive touch edge-swipe to open/close the dockAdam Malczewski
Drag from the left edge to open, or drag the open dock back to close; finger-following with a 50%-or-fling snap on release. New gesture::Controller pure core converges both input paths onto one RevealRecognizer: OPEN via the kernel touch bus (dock hidden at down), CLOSE via UiSurface::bind_drag (the visible dock captures the touch). Slide is value-driven (data-style-transform) and eased only when not dragging. Two real-seat fixes found via per-frame logging: - Flicker: RmlUi projects a drag event's coords into the DRAGGED element's transformed frame. We had drag:drag on the same <body> we translate by slide, so the reported x fed back into slide and ping-ponged every frame. Fix: body is a stationary drag handle; an inner .panel carries the transform. - Direction: drag_start now seeds the recognizer from the dock's current fraction (1 + slide/width) instead of a hardcoded value, so a drag opens or closes correctly from any state.
2026-06-14dock: increase slide transition to 0.36s cubic-in-outAdam Malczewski
2026-06-14ext-stage-dock: full-height left rail — 288px wide, gradient, centered cardsAdam Malczewski
Turn the card-hugging dock into a full-height left rail. - C++ (extension.cpp/dock_layout.hpp): the surface is now the full OUTPUT HEIGHT (hug reverted; content_height helpers/tests dropped) and kDockWidth widened 240 -> 288 (~20%). Cards unchanged at 224dp. set_visible still hides the rail when empty, so it only appears when there are minimized windows. - RCSS (dock.rcss): body.dock fills the surface (width:100% height:100%) as a flex COLUMN scroll container with a `horizontal-gradient(#000000ff #00000000)` decorator — fully-opaque black at the left screen edge fading to transparent across the wider rail. Cards centered both axes (align-items:center + a `div.rail` margin:auto wrapper that vertically centers when they fit and collapses gracefully — no flex-center+overflow strand — scrolling when they overflow). Scrollbars hidden (scrollbarvertical/horizontal size 0). - RML (dock.rml): a `div.rail` wrapper around the data-for slot list enables the center-or-scroll pattern. Accepted caveat (quick path): the full-height 288px surface consumes pointer/touch across the left strip while shown; the deferred input-transparent UiSurfaceSpec flag is the real fix. Real-seat verified via live RML/RCSS hot-reload. ext-stage-dock 2/2 green on build + build-asan.
2026-06-13ext-stage-dock: dock background 50% transparent black (#00000080)Adam Malczewski
2026-06-13ext-stage-dock + build: externalize the dock document to assets/ ↵Adam Malczewski
(hot-reloadable) - The dock's inline kDockRml C++ string is gone; the document now lives in assets/ext-stage-dock/dock.rml (structure) + dock.rcss (styles), loaded via UiSurfaceSpec::rml_path = "ext-stage-dock/dock.rml". The bind_list*/event setup in activate() is unchanged (the substrate re-applies it across hot-reloads). - Build wiring (top-level meson.build): install_subdir the top-level assets/ tree to <datadir>/unbox/<unit>/, and -DUNBOX_ASSET_DIR_DEFAULT=<prefix>/<datadir>/unbox so an installed unbox finds its assets with no env. Dev runs set UNBOX_ASSET_DIR=<repo>/assets + UNBOX_DEV=1 to read the source tree and arm the hot-reload watcher. Real-seat verified: editing dock.rcss (border-radius 10dp<->70dp) updates the live dock with NO recompile and NO restart. ext-stage-dock 2/2 green on build + build-asan. Design iteration on the dock is now edit-a-file.