# Changelog All notable changes to **SignalRGB Desktop Wallpaper** are recorded here. Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and the project follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [2.4.0] - 2026-06-22 High-refresh-monitor smoothness, WE host-compatibility labelling, and an in-Configurator "What's new" modal. ### Added — On-update "What's new" modal in the Configurator Bridge ships per-version release-notes (`RELEASE_NOTES` dict in `bridge.py`, EN + DE bodies) and pushes the current entry on every settings broadcast. The Configurator compares `bridge.appVersion` against the persisted `lastSeenAppVersion`; on mismatch it pops a modal with the release notes once, then writes the current version back so the modal doesn't re-fire until the next bridge update. Header gains an "✨ Neu" / "✨ What's new" button next to *Tour* that re-opens the same modal on demand (no persist-on-dismiss this path — the user has obviously seen the notes by clicking). Both auto-fire and manual paths include an "Open full changelog" button that jumps to the GitHub-hosted CHANGELOG.md. Markdown body uses a tiny inline subset renderer (paragraphs, `**bold**`, `` `code` ``, `-` lists, `**Header**` → `

`) so each version's notes can be hand-written as plain text in `RELEASE_NOTES`. ### Added — "Nur Lively" / "Lively only" badges on three effects Three effects ship in the picker but only render correctly under Lively / WebView2 because Wallpaper Engine's bundled CEF doesn't handle the underlying SVG filters and canvas gradients the way modern Chromium does: - Pixelfx → Hover-Glow (`createRadialGradient` outer stop renders as opaque tinted disc instead of fading to transparent) - Pixelfx → Water-Ripple (`feDisplacementMap` color-space mismatch — entire BG shifts ~22 px even with the `color-interpolation-filters="sRGB"` override) - Mousefx → Liquid Distortion (same SVG-displacement issue as water mode at smaller scale) All three tiles now carry a yellow-amber "Nur Lively" pill in their `.fx-tile-head`, and an explainer hint sits under the Pixelfx grid: "Effekte mit ‚Nur Lively' nutzen SVG-Filter oder Canvas-Gradients die Wallpaper Engine's mitgelieferter CEF nicht korrekt rendert. Unter Lively / WebView2 funktionieren sie sauber." ### Fixed — Ambient effects stuttered when the glow layer was on (high-refresh monitors) User report: on a 240 Hz monitor with Pixel Grid glow at default 30 px blur, ambient / pixelfx effects looked choppy. Disabling the glow layer made them buttery smooth. The choppiness traced to the browser compositor: `#bars` (DOM-mode grid) and `#bars-canvas` (canvas-mode grid) were *not* on their own composite layers. Every source-data update into the grid (via WS message → DOM style writes or putImageData) forced the page to re-composite the WHOLE layer stack including the blurred glow output. At 240 Hz refresh rate the browser tried to re-blur the full grid every 4.17 ms, saturated the main thread, and the ambient/pixelfx rAF callbacks were starved. Fix: explicit GPU-layer promotion on the glow grid and on the ambient / pixelfx canvases: ```css /* #bars.lay-grid + #bars-canvas */ will-change: filter; isolation: isolate; /* #ambient-canvas + #pixelfx-canvas */ will-change: transform; isolation: isolate; ``` The browser now caches each layer's output between source-frame updates and re-blends them at monitor refresh without recomputing the blur. Memory cost: ~30 MB GPU per promoted layer on a 5120×1440 setup (so ~120 MB resident when all four effect canvases are active). Acceptable on modern GPUs; the perf win is dramatic. `#audioglow-canvas` deliberately NOT promoted — its `mix-blend-mode: screen` needs the parent composite to be flat for the blend math to read the layer beneath. ### Changed — Grid renderer dropdown defaults to Canvas, labelled "recommended" The bridge default has been Canvas since v1.2.12, but the Configurator's dropdown listed DOM first and labelled it "lower GPU" — which read as "the better choice" to users who don't know the trade-off. After the high-refresh stutter investigation above, the truth is the opposite for most modern setups: - **Canvas**: one `putImageData` per frame, main thread free, smooth ambient / pixelfx rAFs. Slightly more GPU because the browser bilinear-upsamples + blurs the small grid texture. - **DOM**: up to 1024 `style.background` writes per frame on a 32×32 grid. Cheap on GPU (just solid-rect composites), but saturates the main thread on high-refresh monitors and starves other rAF chains. Dropdown now lists Canvas first as "Canvas (recommended)" / "Canvas (empfohlen)" and DOM second as "DOM (legacy)" / "DOM (alt)". A hint line below explains: "Canvas: smoothere Ambient-Effekte auf High-Refresh-Monitoren (240 Hz etc.). DOM nur wenn deine GPU mit dem Canvas-Blur überfordert ist." ### Changed — APP_VERSION + WALLPAPER_VERSION → 2.4.0 Wallpaper code changed (CSS layer-isolation). Re-import IS required for Lively + WE. MINOR cut, so this release goes to winget alongside the GitHub release (per `feedback-winget-release-pacing`). ## [2.3.0] - 2026-06-17 Stable cut of the 2.3.x beta wave (2.3.0-beta → 2.3.13-beta). Major themes: in-wallpaper pack browser, atmosphere effects + widget skins, cursor-effect overhaul, GPU/RAM optimisation pass, water ripple as real BG refraction, Configurator i18n sweep. ### Added - **In-app wallpaper pack browser** — Library tab now browses curated pack manifests hosted on GitHub Pages. Tiles preview the bundled wallpapers; click adds the whole pack to the local library. Backed by `library-packs.json` in the docs repo so new packs land for everyone without a Configurator update. - **Atmosphere effects** — new `storm` ambient preset combines rain particles with a lightning flash subsystem (random strikes, occasional doubles); `water ripple` pixelfx mode bends the background image along a propagating SVG-displacement wave on every click; `weather-reactive ambient` ambient picks the right preset based on the live WMO code from Open-Meteo. - **Widget skin system** — every widget type can ship alternate skins under `WIDGET_REGISTRY[type].skins.`. Weather ships three: default, compact, hexagon. Skin picker lands in the per-widget edit dialog. - **Cursor-effect tile UI** — the four stackable cursor distortions (Liquid Distortion / Chromatic Halo / Spotlight / Widget Float) moved from the Widgets card to the Effects tab and picked up a tile grid replacing the v1.6 checkbox row. The Pixelfx mode picker also moved to the same tile layout (v2.3.9). - **Floating lock pill** — while widgets are unlocked, an on-screen pill at top-center carries a Lock button so users can re-lock without going back to the Configurator. - **In-page Quick Looks tiles + 10 bundled looks**, all i18n'd in v2.3.13: Cyberpunk Streamer, Minimal Productivity, Gaming, Music Studio, Holiday Vibes, News Desk, Focus Mode, Stream Overlay, Pomodoro, Minimal Calendar. ### Changed - **Memory + GPU pass**: full-viewport canvases (ambient / pixelfx / audio-glow / bars) collapse their backing buffer to 1×1 when idle (~30 MB saved per canvas per WebView2 instance on a 5120×1440 setup); pixelfx + audioglow gained the same SCALE × DPR bucket ambient already had (Performance bucket = 0.5× = 4× fewer pixels per frame); Widget Float repulsion no longer juggles 2N in-flight CSS transitions every render tick; Stripes/Pills bar layouts no longer hold N background transitions for the same reason; audio-spectrum widget now redraws at 30 Hz via a new counter-gated rAF path instead of being stuck at 1 fps. - **Pixelfx single-select**: the "All" stack-everything mode is gone (v2.3.11). Modes are exclusive — pick exactly one of trail, hover-glow, click ripple, water ripple. Persisted `all` values fall back to `off`. - **Configurator i18n sweep** (v2.3.13): `applyI18n` gained independent attribute translation slots (`data-i18n-title`, `data-i18n-placeholder`, `data-i18n-aria-label`, `data-i18n-alt`); all Quick Looks bundles, widget catalog labels, glow / glass-quality / frame-rate / grid-renderer dropdowns, and header tooltips now follow the active language. Add-Widget grid + Quick-Looks grid rebuild on language switch so initial-paint fallbacks don't stick. ### Fixed - **Water mode shifted the whole BG**: SVG filter color-space mismatch — Chromium runs feDisplacementMap in linear-RGB by default, but the displacement map canvas exports as sRGB PNG. R=128 sRGB → 0.215 linear → constant -22 px shift across the non-ring area. Added `color-interpolation-filters="sRGB"` on the filter element so the chain stays sRGB end-to-end. - **Memory leaks**: Liquid Distortion's per-frame `toDataURL` was leaking ~1 MB/s of decoded SVG-filter bitmaps in Chromium's cache; activity-gated to skip the encode + setAttribute when the cursor is idle. Spotlight allocated a fresh CSS gradient string per frame; refactored to mutate CSS vars only. - **Cursor effects ignored fullscreen pause**: all four MouseFx ticks gained the same `if (isPaused) return` guard the ambient/pixelfx rAF chains already had, plus a wallpaper-resume listener so they re-arm correctly. - **Library + bulk-select edge cases**: deleting all tag-filtered items used to blank the library until refresh; deleting via bulk-select with a filter active left orphan `_libraryPack` / `_libraryTag` state; the × delete button overlapped the selection checkbox. All addressed in v2.3.1 / v2.3.2. ### Upgrade Wallpaper bundle re-import IS required. Tray → Re-import wallpaper bundles. This is a MINOR cut — winget submission tracked separately. ## [2.3.13-beta] - 2026-06-17 Water-ripple gap fix + Configurator i18n sweep. ### Fixed — Water-mode shifted the whole BG, not just the ring band The v2.3.12 scale=0 default fix stopped the activation jump, but during an active ripple the BG still appeared shifted across the entire viewport — not just where the ring band crossed. Root cause: SVG filter color-space mismatch. Chromium runs `feDisplacementMap` in linear-RGB by default, but our displacement map canvas exports as sRGB-encoded PNG. The sRGB → linear conversion remaps R=128 from 0.502 down to ~0.215, which means the "neutral grey" the canvas paint assumes (R=G=128 → 0 displacement) actually encodes `(0.215 - 0.5) × scale = -22.8 px` displacement across the **entire non-ring area** of #bg. Net visual: the whole BG slid -22 px up-left whenever a ripple was in flight; the ring band's intended displacement layered on top. Fix: `color-interpolation-filters="sRGB"` on the filter element. Forces the chain to operate in sRGB throughout, matching the PNG encoding — R=128 now produces the 0-displacement the paint math always intended. ### Configurator i18n sweep Large chunks of the UI still rendered in English when the language was switched to DE. ### Fixed — applyI18n() couldn't target attributes The pre-v2.3.13 `data-i18n-attr="placeholder"` mechanism collected the `attr` value as a `{attr}` template parameter instead of using it to target the placeholder attribute. Net effect: the search input's placeholder stayed English no matter what. Rewrote applyI18n to support two new patterns: * `data-i18n-attr=""` (backward-compat) — pipes the main `data-i18n` value into the named attribute instead of textContent * `data-i18n-=""` for each of `title`, `placeholder`, `aria-label`, `alt` — independent attribute translation slots. Lets a button carry a translated label AND a translated tooltip via two separate keys. ### Added — Quick Looks bundle i18n (10 × name + desc) Every `LOOK_BUNDLES` entry now carries `nameKey` / `descKey` keys. `renderLookBundles` writes the keys onto the rendered tile DOM via `data-i18n` so `applyI18n` re-translates on language toggle; `applyLookBundle`'s confirm dialog uses the translated name + localised screen label too. Added 20 EN/DE entries. ### Added — Widget catalog labels i18n (13 × widget type names) Every `WIDGET_CATALOG` entry now carries `labelKey`. New `_widgetLabel(def)` helper resolves to the translated form, falling back to the English literal if the translation is missing. Replaced 5 direct `def.label` reads (layout preview, add grid, widget list, remove toast, modal title) + 2 toast string templates ("Added X" / "Removed X") with `t()` calls. The Add-Widget grid + Quick-Looks grid are now rebuilt by `renderAll` on language switch since both are built once at boot. ### Added — Translation entries for dropdowns + tooltips * Glow layout dropdown (5 options) * Grid renderer dropdown (2 options) * Glass quality dropdown (3 options) * Frame rate dropdown (3 options) * Header `title` tooltips for Live preview, Show tour, Open library All static `