mirror of
https://github.com/kilyabin/psysonic.git
synced 2026-07-28 09:26:41 +00:00
fix(windows): tray double-click flicker + GPU use when minimized
1. Tray double-click (reported by @cucadmuh's brother-in-law): Windows fires a Click event on *both* halves of a double-click, so our left-click handler toggled visibility twice — the window popped up and immediately vanished. Switch the Windows branch to the `TrayIconEvent::DoubleClick` variant (Windows-only in tray-icon); other platforms keep the Click-on-Up behaviour. Matches the standard Windows tray convention (Discord, Telegram, etc). 2. GPU use while minimized: WebView2 on Windows keeps compositing infinite CSS animations (mesh-aura-a/b, portrait-drift, eq-bounce, track-pulse, led-pulse …) even when the window is minimized — steady visible GPU load on systems that should be idle. App.tsx now toggles a `data-app-hidden="true"` attribute on <html> on `visibilitychange`, and a single CSS rule pauses every `animation` at once via `animation-play-state: paused !important`. Zero cost when visible, catches all current and future infinite animations without per-element listeners. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+20
-5
@@ -2432,11 +2432,26 @@ fn build_tray_icon(app: &tauri::AppHandle) -> tauri::Result<TrayIcon> {
|
|||||||
_ => {}
|
_ => {}
|
||||||
})
|
})
|
||||||
.on_tray_icon_event(|tray, event| {
|
.on_tray_icon_event(|tray, event| {
|
||||||
if let TrayIconEvent::Click {
|
// Windows fires a Click on *every* half of a double-click, so a
|
||||||
button: MouseButton::Left,
|
// double-click would toggle the window visibility twice and end up
|
||||||
button_state: MouseButtonState::Up,
|
// back where it started (the bug #cucadmuh reported). Switch to the
|
||||||
..
|
// Windows-only DoubleClick event there and ignore single clicks;
|
||||||
} = event {
|
// that matches the standard Windows tray convention (Discord, etc).
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
let should_toggle = matches!(
|
||||||
|
event,
|
||||||
|
TrayIconEvent::DoubleClick { button: MouseButton::Left, .. }
|
||||||
|
);
|
||||||
|
#[cfg(not(target_os = "windows"))]
|
||||||
|
let should_toggle = matches!(
|
||||||
|
event,
|
||||||
|
TrayIconEvent::Click {
|
||||||
|
button: MouseButton::Left,
|
||||||
|
button_state: MouseButtonState::Up,
|
||||||
|
..
|
||||||
|
}
|
||||||
|
);
|
||||||
|
if should_toggle {
|
||||||
let app = tray.app_handle();
|
let app = tray.app_handle();
|
||||||
if let Some(win) = app.get_webview_window("main") {
|
if let Some(win) = app.get_webview_window("main") {
|
||||||
if win.is_visible().unwrap_or(false) {
|
if win.is_visible().unwrap_or(false) {
|
||||||
|
|||||||
+14
@@ -325,6 +325,20 @@ function AppShell() {
|
|||||||
};
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
// Pause CSS animations when the window is minimized / hidden.
|
||||||
|
// WebView2 on Windows keeps compositing infinite-loop animations (mesh-aura,
|
||||||
|
// portrait-drift, eq-bounce, …) even when the app is minimized, which shows
|
||||||
|
// up as steady GPU usage. The CSS rule `html[data-app-hidden="true"]` in
|
||||||
|
// components.css pauses all running animations while this flag is set.
|
||||||
|
useEffect(() => {
|
||||||
|
const update = () => {
|
||||||
|
document.documentElement.dataset.appHidden = document.hidden ? 'true' : 'false';
|
||||||
|
};
|
||||||
|
document.addEventListener('visibilitychange', update);
|
||||||
|
update();
|
||||||
|
return () => document.removeEventListener('visibilitychange', update);
|
||||||
|
}, []);
|
||||||
|
|
||||||
const isMobilePlayer = isMobile && location.pathname === '/now-playing';
|
const isMobilePlayer = isMobile && location.pathname === '/now-playing';
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -8804,3 +8804,15 @@ html.no-compositing .fsr-lyric-line.fsrl-active .fsr-lyric-word.active {
|
|||||||
|
|
||||||
.device-sync-row-name { flex: 1; font-size: 0.85rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
.device-sync-row-name { flex: 1; font-size: 0.85rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
||||||
.device-sync-row-meta { font-size: 0.75rem; color: var(--text-secondary); flex-shrink: 0; }
|
.device-sync-row-meta { font-size: 0.75rem; color: var(--text-secondary); flex-shrink: 0; }
|
||||||
|
|
||||||
|
/* ── Pause CSS animations when the window is hidden / minimized ────────────
|
||||||
|
Set via App.tsx on `visibilitychange`. WebView2 on Windows keeps compositing
|
||||||
|
infinite CSS animations (mesh-aura, portrait-drift, eq-bounce, track-pulse,
|
||||||
|
led-pulse, …) even when the app is minimized, causing constant GPU use.
|
||||||
|
Pausing them cuts that to near zero while hidden without touching the
|
||||||
|
running Rust/audio threads. */
|
||||||
|
html[data-app-hidden="true"] *,
|
||||||
|
html[data-app-hidden="true"] *::before,
|
||||||
|
html[data-app-hidden="true"] *::after {
|
||||||
|
animation-play-state: paused !important;
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user