From 402e288a243799eba629688117bd988353f9d2a1 Mon Sep 17 00:00:00 2001 From: Frank Stellmacher <171614930+Psychotoxical@users.noreply.github.com> Date: Sat, 2 May 2026 23:20:01 +0200 Subject: [PATCH] fix(css): scope data-app-blurred animation pause away from `*` (#434) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix(css): scope data-app-blurred animation pause away from `*` The `data-app-blurred="true"` rule used a `*` selector to pause every animation while the window was unfocused. On WebKitGTK + no-compositing (Linux dev mode) this triggered a stale rendering bug after Vite HMR reloads — the sidebar and main content stayed invisible until any user interaction nudged a re-render. Splitting the rule: * `data-app-hidden` and `data-psy-native-hidden` keep `*` because the window is fully invisible to the user in those states. * `data-app-blurred` now lists only the concrete heaviest infinite animations (eq bars, marquees, np dot pulse, fullscreen mesh blob / portrait, generic spin). The other small animations keep running while blurred — minor GPU cost compared to the broken HMR experience. The JS-side `__psyBlurred` flag in WaveformSeek is unchanged. * docs(changelog): add #434 entry to [1.45.0] / Fixed --- CHANGELOG.md | 2 ++ src/styles/components.css | 22 ++++++++++++++++++---- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c9fc5a2f..b0b2df9d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -141,6 +141,8 @@ The currently playing row in the queue list is now indicated by **animated equal - **Windows playback stutter under GPU load** *(Issue [#334](https://github.com/Psychotoxical/psysonic/issues/334), PR [#426](https://github.com/Psychotoxical/psysonic/pull/426), by [@Psychotoxical](https://github.com/Psychotoxical))*: Audio could stutter and crackle on Windows whenever another app put GPU/CPU pressure on the system (browser, 3D apps, games). The WASAPI render thread is now promoted to MMCSS "Pro Audio" via `AvSetMmThreadCharacteristicsW`, so it survives priority contention from competing graphics work. Reproed and validated under a Half-Life parallel-load stresstest. Companion mitigations for high-GPU situations: cosmetic UI animations now pause when the window loses OS focus, and a new **Reduce animations** toggle in **Settings → Appearance** caps animated seekbar styles (pulsewave, particletrail, liquidfill, retrotape) to 30 fps for users on GPU-constrained machines (off by default). +- **Linux dev — sidebar and main content invisible after HMR** *(PR [#434](https://github.com/Psychotoxical/psysonic/pull/434), by [@Psychotoxical](https://github.com/Psychotoxical))*: The `data-app-blurred="true"` CSS rule introduced in #426 used a `*` selector to pause every animation while the window was unfocused. On WebKitGTK + no-compositing this triggered a stale rendering bug after Vite hot-reloads — the sidebar and main content stayed unpainted until any user interaction nudged a re-render. The rule now targets only the concrete heaviest infinite animations (eq bars, marquees, now-playing dot pulse, fullscreen mesh blob / portrait, `.spin`); release builds are unchanged in behaviour. + ## [1.44.0] - 2026-04-29 diff --git a/src/styles/components.css b/src/styles/components.css index f6113a85..3b75501b 100644 --- a/src/styles/components.css +++ b/src/styles/components.css @@ -11097,15 +11097,29 @@ html.no-compositing .fs-seekbar-played { background: var(--accent); } +/* Window completely invisible (tab hidden via Visibility API, or Tauri + `win.hide()`): pausing every animation is safe because the user is not + looking. */ html[data-app-hidden="true"] *, html[data-app-hidden="true"] *::before, html[data-app-hidden="true"] *::after, html[data-psy-native-hidden="true"] *, html[data-psy-native-hidden="true"] *::before, -html[data-psy-native-hidden="true"] *::after, -html[data-app-blurred="true"] *, -html[data-app-blurred="true"] *::before, -html[data-app-blurred="true"] *::after { +html[data-psy-native-hidden="true"] *::after { + animation-play-state: paused !important; +} + +/* Window visible but unfocused (alt-tab, click into another app): only + pause the heaviest known infinite animations to save GPU. The previous + `*`-selector variant fired a repaint over every node and triggered a + stale-blur HMR rendering bug on WebKitGTK + no-compositing. */ +html[data-app-blurred="true"] .eq-bars .eq-bar, +html[data-app-blurred="true"] .player-marquee, +html[data-app-blurred="true"] .marquee-text, +html[data-app-blurred="true"] .np-dot-pulse, +html[data-app-blurred="true"] .fs-mesh-blob, +html[data-app-blurred="true"] .fs-portrait-wrap, +html[data-app-blurred="true"] .spin { animation-play-state: paused !important; }