feat(lyrics): lite-fill display pref — static active-line highlight to cut CPU

The per-word karaoke sweep animates a clip rect ~60x/s, driving continuous full-window repaints (~4% CPU). Lite fill highlights the active line whole (no per-frame animation) so the surface only repaints on line changes. New toggle in the lyrics controls flyout, persisted via lyrics_prefs; default off (smooth karaoke). Kiosk / weak-GPU tiers force it on via ShellState.reduce-motion.

cc
This commit is contained in:
vicrodh committed 2026-07-12 19:38:43 -06:00
1 parent 5fa4e8bdd5
commit ec8c487564
4 files changed
+44 -7

No files matched your search

@@ -176,6 +176,21 @@ export component LyricsControlsPanel inherits Rectangle {
}
}
// Lite fill (perf): highlight the active line whole instead of the
// per-word karaoke sweep — stops the continuous full-window repaints.
HorizontalLayout {
height: 22px;
spacing: 8px;
RowLabel { text: @tr("Lite fill (saves CPU)"); }
QbzToggle {
checked: LyricsState.lite-fill;
toggled(v) => {
LyricsState.lite-fill = v;
LyricsState.prefs-changed();
}
}
}
// Dimming (Tauri segmented Off/Soft/Strong -> select).
HorizontalLayout {
height: 30px;
+14 -7
View File
@@ -44,7 +44,7 @@
import { Theme } from "../foundation/semantic-colors.slint";
import { Typography } from "../foundation/typography.slint";
import { LyricsState, LyricsSegment } from "../state.slint";
import { LyricsState, LyricsSegment, ShellState } from "../state.slint";
// Q6 (SHIPPED): Tauri's four non-system lyric font families, embedded into
// the binary at compile time (slint-build default EmbedAllResources for Rust
@@ -218,17 +218,24 @@ component LyricsLineRow inherits VerticalLayout {
// Bright (sung) overlay, clipped to this segment's LOCAL fill.
// local = clamp((line-progress - start-weight) / width-weight, 0, 1)
Rectangle {
// Lite fill (pref) or reduce-motion (kiosk / weak GPU): the
// active line is fully lit and STATIC — no per-frame clip
// animation, so the surface stops repainting the whole window
// ~60x/s just to sweep the karaoke fill.
property <bool> cheap: ShellState.reduce-motion || LyricsState.lite-fill;
x: 0;
y: 0;
width: segbase.width * Math.clamp(
seg.width-weight > 0
? (LyricsState.line-progress - seg.start-weight) / seg.width-weight
: 0,
0.0, 1.0);
width: self.cheap
? segbase.width
: segbase.width * Math.clamp(
seg.width-weight > 0
? (LyricsState.line-progress - seg.start-weight) / seg.width-weight
: 0,
0.0, 1.0);
height: segbase.height;
clip: true;
animate width {
duration: LyricsState.fill-anim-ms * 1ms;
duration: self.cheap ? 0ms : LyricsState.fill-anim-ms * 1ms;
easing: linear;
}
Text {
+6
View File
@@ -4220,6 +4220,12 @@ export global LyricsState {
// 0 off · 1 soft · 2 strong (Tauri default 'strong').
in-out property <int> dimming-mode: 2;
in-out property <bool> uppercase: false;
// Lite fill (perf): when true, the active line is highlighted whole instead
// of the per-word karaoke sweep — no per-frame clip animation, so the lyrics
// surface stops driving continuous full-window repaints (~4% CPU -> idle
// between line changes). Default false (smooth karaoke). Kiosk / weak-GPU
// tiers force it on via ShellState.reduce-motion regardless of this pref.
in-out property <bool> lite-fill: false;
// Active (karaoke fill) color. `use-custom-color: false` = follow the theme
// accent (Tauri activeColor: ''). The palette swatches set both (deviation
// D6: swatches instead of a native color input — Slint has none).