perf(less-computer-glow): 隐藏时卸载全屏发光层,消除空闲 GPU 占用 (#675)

issue #470:彩虹描边 glow 是全屏 transparent 浮层 + 4 条无限动画(lcg-spin/breathe/
spin-reverse/flow)。原组件无状态无监听,窗口 .hide() 后 webview 仍持续合成发光层、
跑满 4 条动画,GPU 永不释放(Windows 尤其不释放)。

改为后端 show/hide 主动 emit `less-computer-glow:active` 驱动可见状态(不依赖在隐藏
窗口上失灵的 WebView2 visibilitychange):可见时渲染与原来完全一致的 DOM(视觉零变化),
不可见时返回 null 卸载发光层 → 零 GPU。另加 document.hidden 二级兜底(只停不启)。

注:glow 当前为 macOS-only(Windows show/hide 是 no-op),本修复消除 macOS 隐藏态泄漏,
并让组件具备跨平台「隐藏即零 GPU」安全性,为后续 Windows 重启用铺路。

Co-authored-by: 吕柏青 <lubaiqing9@gmail.com>
This commit is contained in:
TRIPand吕柏青 authored and GitHub committed 2026-06-16 10:56:27 +08:00
1 parent 28ea5123b4
commit 9f3eebcb88
2 files changed
+36

No files matched your search

+5
View File
@@ -2181,6 +2181,8 @@ pub(crate) fn show_less_computer_glow<R: tauri::Runtime>(app: &AppHandle<R>) {
}
// 点击穿透:纯视觉浮层,绝不拦截鼠标。
let _ = window.set_ignore_cursor_events(true);
// issue #470:通知 glow 前端「可见」,恢复发光动画(隐藏时会 emit(false) 卸载发光层以释放 GPU)。
let _ = window.emit("less-computer-glow:active", true);
let window_clone = window.clone();
let _ = app.run_on_main_thread(move || {
use objc2::msg_send;
@@ -2215,6 +2217,9 @@ pub(crate) fn show_less_computer_glow<R: tauri::Runtime>(_app: &AppHandle<R>) {}
#[cfg(target_os = "macos")]
pub(crate) fn hide_less_computer_glow<R: tauri::Runtime>(app: &AppHandle<R>) {
if let Some(window) = app.get_webview_window("less-computer-glow") {
// issue #470:先通知前端「不可见」卸载全屏发光层(4 条无限动画),webview 隐藏后即零 GPU;
// 否则 .hide() 后 webview 仍持续合成发光层(Windows 尤其不释放动画)。
let _ = window.emit("less-computer-glow:active", false);
let _ = window.hide();
}
}
@@ -2,6 +2,8 @@
// 只画贴边光带,不铺暗场;彩色弧段沿边缘流动,模拟 Apple Intelligence 的粗细变化。
// 纯视觉:pointer-events:none,后端再 set_ignore_cursor_events(true)。仅 macOS 显示。
import { useEffect, useState } from 'react';
const glowCss = `
@property --lcg-angle { syntax: '<angle>'; initial-value: 0deg; inherits: false; }
@keyframes lcg-spin { to { --lcg-angle: 360deg; } }
@@ -93,6 +95,35 @@ if (typeof document !== 'undefined' && !document.getElementById('less-computer-g
}
export function LessComputerGlow() {
// issue #470:窗口 .hide() 后 webview 不会自动停掉这 4 条无限动画(Windows 尤其不释放),
// 全屏发光层持续占 GPU 合成。改由后端 show/hide 主动 emit 可见状态驱动:不可见时直接卸载
// 发光层(无元素 → 零 GPU),可见时原样渲染——显示时视觉零变化。
const [active, setActive] = useState(true);
useEffect(() => {
let cancelled = false;
let unlisten: (() => void) | undefined;
void import('@tauri-apps/api/event').then(({ listen }) => {
if (cancelled) return;
void listen<boolean>('less-computer-glow:active', (e) => {
setActive(Boolean(e.payload));
}).then((un) => {
if (cancelled) un();
else unlisten = un;
});
});
// 二级兜底:页面被标记为隐藏时也停(只停不启,绝不误关正在显示的发光)。
const onVisibility = () => {
if (document.hidden) setActive(false);
};
document.addEventListener('visibilitychange', onVisibility);
return () => {
cancelled = true;
unlisten?.();
document.removeEventListener('visibilitychange', onVisibility);
};
}, []);
if (!active) return null;
return (
<div className="lcg-root" aria-hidden>
<span className="lcg-flow" />