Skip to content

Desktop background mode: independently positioned panels (floating + WorkerW) #170

Description

@dvalfrid

Goal

Combine floating mode's per-panel independent positioning/dragging with Desktop Wallpaper mode's WorkerW integration, so each panel is its own small window living in the desktop background layer (survives Win+D, sits behind desktop icons, never covers anything) instead of the wallpaper host's current single fixed dashboard layout.

Explicitly not in scope here: per-pixel transparency. See "Scope: opaque only" below.

Background — what already exists and works

Two pieces of this are already built and proven, separately:

  1. Per-panel independent windowingsrc-egui/src/main.rs::render_floating_panels. Each visible panel is its own OS window via ctx.show_viewport_immediate, individually draggable, position persisted per panel key in Settings::floating_positions. Handles drag zones, padlock lock/unlock, per-panel auto-resize-to-content, and (for "Always Behind") a throttled HWND_BOTTOM re-assertion (win32_behind.rs) to avoid a CPU-spiking repaint loop.
  2. WorkerW reparentingsrc-egui/src/win32_wallpaper.rs. attach(hwnd) / is_attached(hwnd) / detach(hwnd), proven working (issue Spike: per-pixel translucency in Desktop Wallpaper mode via DirectComposition #131): survives Win+D, sits behind icons, re-attaches if Explorer rebuilds the WorkerW hierarchy. Currently used for exactly one HWND — the single rigstats-wallpaper host window.

The wallpaper host is a separate process (rigstats-wallpaper.exe) specifically because a WorkerW child window is destroyed if Explorer restarts — cross-process included — so reparenting the main app's own window would risk taking the whole app down with it. See docs/architecture.md "Desktop wallpaper mode (WorkerW)".

Proposed approach

  • Generalize the wallpaper host (src-egui/src/bin/wallpaper.rs) from "one fixed-layout window" to "N independently-positioned panel windows," reusing render_floating_panels' per-panel viewport/drag/position code (adapted to the host binary) and win32_wallpaper.rs's attach/re-attach logic generalized from a single self.hwnd: isize to a HashMap<String, isize> keyed by panel key — each panel gets its own attach-on-creation + periodic is_attached safety net.
  • Keep it a single host process, not one process per panel. The host already owns telemetry polling (poll_loop) and the sensor pipe's single client slot; N separate processes would mean either N independent pollers (wasteful, duplicates GPU/CPU/WMI polling work — directly against the resource-utilization concern raised when scoping this) or new inter-process telemetry distribution (real added complexity for no clear benefit). One process rendering N viewports is the natural fit and mirrors what floating mode already does today within the main process.
  • Each panel window still needs the existing "cache HWND on first frame, SetParent into WorkerW, periodic is_attached re-check" sequence — per-window state, not global.

Scope: opaque only (no per-pixel transparency in this issue)

Keep panels opaque (or using the existing WS_EX_LAYERED uniform-dim opacity, same as floating mode has today) for this issue. Per-pixel translucency is a separate, harder problem: issue #169 (extend #101's DComp per-pixel transparency to floating mode) found that applying WS_EX_NOREDIRECTIONBITMAP to a secondary show_viewport_immediate viewport's HWND breaks its rendering (washed-out color), reproduced with zero opacity logic involved — a real eframe 0.34.3/egui-wgpu limitation in how the swap-chain surface is created for non-root immediate viewports combined with a DComp (DxgiFromVisual) backend. This issue's multi-window wallpaper host would hit the exact same limitation if it tried to add translucency. Do this issue without transparency first; revisit combining it with #169 once that's resolved.

Risks / open questions

  • Explorer-restart robustness at N windows instead of 1. The existing single-window re-attach safety net (is_attached polled ~1/s, re-attach() if detached) generalizes mechanically to a loop over N HWNDs, but there's more surface area for something to go wrong — verify no crash/hang if Explorer restarts while several panels are attached.
  • Panel add/remove while running. Floating mode already handles a panel being toggled visible/invisible mid-session (main.rs's panels_positioned tracking). The host needs the same for its own per-panel HWND map — attach newly-shown panels, clean up state for hidden ones (their OS window is presumably destroyed by show_viewport_immediate simply no longer being called for that key each frame — confirm this doesn't leak).
  • Resource cost. Should stay roughly comparable to today's floating mode (same N-viewport-per-frame rendering cost that Floating mode - reduce multi-window rendering cost #104 already investigated and accepted as not worth optimizing further) plus today's single-window wallpaper host's WorkerW-attach overhead, multiplied by N. Worth a before/after CPU measurement (same methodology Floating mode - reduce multi-window rendering cost #104 used: TotalProcessorTime delta over 10s) once implemented, given resource utilization was explicitly flagged as a priority while scoping this.
  • Settings/UX: does this become a new "Window Layer" option (e.g. "Desktop Wallpaper — Floating"), or a checkbox/toggle combining the existing "Desktop Wallpaper" layer with the existing "Floating Mode" toggle (currently mutually exclusive — wallpaper mode force-disables floating mode, see main.rs around the window-layer selector)? Needs a decision before implementing the Settings UI change.

Acceptance criteria

  • Each visible panel renders as its own window living in the WorkerW desktop-background layer: survives Win+D, sits behind desktop icons, doesn't cover anything.
  • Panels remain individually draggable/positionable, with positions persisted the same way floating mode already does.
  • Re-attaches correctly after an Explorer restart, for all currently-attached panels.
  • No meaningful resource-usage regression vs. today's floating mode + wallpaper mode individually (measure, don't assume).
  • Opaque / WS_EX_LAYERED-dimmed only — no attempt at per-pixel transparency in this issue.

Related issues

Affected files (entry points)

  • src-egui/src/bin/wallpaper.rs — the host; needs the per-panel windowing loop
  • src-egui/src/main.rs::render_floating_panels — source of the per-panel viewport/drag/position logic to adapt
  • src-egui/src/win32_wallpaper.rs — attach/is_attached/detach, needs generalizing to N HWNDs
  • src-egui/src/windows/settings.rs — Settings UX decision (new layer option vs. combined toggle)
  • docs/architecture.md "Desktop wallpaper mode (WorkerW)" — update once shipped

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions