DHEnry 949c7bf558 Align font runs on the baseline, not the ink centre
Reported: with a separate Latin font the Latin text sat even higher than
before. Measuring the user's pair (KaiTi + DejaVu Sans at 40px) explains
why: DejaVu's ink box is -50..13 while KaiTi's is -46..8, so their centres
differ by only 0.5px but the Latin box extends further both up and down.
Centre alignment therefore leaves the extra ~4px of Latin hanging above the
CJK glyphs, which is exactly what reads as 'Latin too high'.

Line-box baselines for the same size are KaiTi 7, DejaVu Sans 1, Noto CJK 5.
Aligning on the baseline keeps the glyph bottoms together (measured: 12 vs
13 for KaiTi+DejaVu, 16 vs 16 for Noto CJK+DejaVu).

The run field is carried through explicitly and a missing value falls back
to 'no shift', so the earlier stacking regression cannot recur silently.
Also skip _syncSize() once the overlay is being finalized, which removes
the remaining shutdown warnings.

Tests: 35 unit tests updated for baseline semantics.
2026-11-11 20:12:05 +08:00

LX Music Lyrics

一个面向 LX Music(洛雪音乐助手)+ GNOME Shell(Wayland) 的外置桌面歌词 GNOME Shell 扩展。

  • 永远悬浮在普通窗口之上,不受 Super+D(显示桌面)影响
  • 锁定后完全鼠标穿透(不可拖动、不可点击)
  • 支持 逐字卡拉OK高亮(lxlyric)、翻译(tlyric)、粤拼/罗马音(rlyric)
  • 鼠标悬停在歌词上时自动淡出隐藏,离开后恢复
  • 可配置字体、字号、已播放/正在播放/未播放/翻译/粤拼颜色、描边/背景
  • 顶栏菜单控制:显示/锁定/翻译开关、播放/暂停、上一首/下一首、重新加载歌词
  • 全局快捷键

为什么是 GNOME Shell 扩展而不是普通窗口?

GNOME 50 的 Mutter 仍不支持 wlr-layer-shell,普通 Wayland 客户端无法可靠地自行定位、置顶、点击穿透;Electron 桌面歌词在 Wayland 下问题更多。扩展直接把歌词绘制在 Main.uiGroup 上,因此可以同时做到:永远在普通窗口之上、不受显示桌面影响、锁定后完全穿透、用 global.get_pointer() 实现悬停隐藏、自由定位并支持多显示器。

依赖与前置条件

  • GNOME Shell 50 / 51(Ubuntu 26.04+ 或同等版本),Wayland 或 X11 均可
  • LX Music 桌面版 2.x,已开启 开放 API:
    • LX Music → 设置 → 开放 API → 开启
    • 默认地址 http://127.0.0.1:23330,可在本扩展设置中修改
  • glib-compile-schemas(安装脚本需要,libglib2.0-bin 自带)

安装

./install.sh
gnome-extensions enable lx-music-lyrics@dhenry

Wayland 下新安装的扩展通常需要注销并重新登录后才能加载。

卸载:

./uninstall.sh

使用说明

  • 显示/隐藏:顶栏菜单开关,或快捷键 Super+Alt+L
  • 锁定/解锁:默认锁定(完全穿透)。解锁方式:顶栏菜单“锁定歌词”开关,或 Super+Alt+K;解锁后歌词出现虚线边框,可用鼠标左键拖动位置,松手自动保存并重新钳制到屏幕内
  • 悬停隐藏:锁定状态下鼠标进入歌词区域,约 250ms 后淡出;离开后恢复(可在设置中调整或关闭)
  • 播放控制:顶栏菜单或 Super+Alt+P(播放/暂停)、Super+Alt+Right(下一首)、Super+Alt+Left(上一首)
  • 歌词内容:
    • 主歌词:lyric;若存在 lxlyric 且开启“逐字高亮”,则按字点亮
    • 没有 lxlyric 时按整行进度擦除,播放头用“正在播放”颜色标出
    • 翻译:tlyric;粤拼/罗马音:rlyric(粤语歌即为粤拼,如《光辉岁月》)
  • 字体:歌词字体与字号分开设置(字体选择器只管字体族,字号用独立滑块);可另设西文字体,只影响英文/数字部分,中英文可各用一种字体
  • 动画:换行时新行从「起始缩放」放大到 100% 并逐渐加亮,上一行同步缩小变暗;动画时长、起始缩放可调,设为 0 / 1.0 即关闭
  • 长歌词:当前行超宽时跟随正在演唱的字平滑滚动,不会跳格
  • 设置:顶栏菜单“设置…”打开偏好窗口(中文),可调字体、颜色、布局、动画、行为、快捷键、API 地址

故障排查

# 1. LX Music API 是否可达
curl http://127.0.0.1:23330/status?filter=status,name

# 2. 扩展状态
gnome-extensions info lx-music-lyrics@dhenry

# 3. 查看 gnome-shell 日志中的扩展输出
journalctl --user -b -o cat | grep -i "lx-music\|lx lyrics"
  • 歌词不显示:先确认 API 可达;确认顶栏菜单里“显示歌词”已开启;确认 LX Music 正在播放
  • 扩展未加载:确认 schema 已编译(install.sh 会执行 glib-compile-schemas);重新登录
  • 快捷键冲突:设置 → 快捷键 中修改

开发与测试

npm test   # 纯 JS 模块(lib/lrc.js)单元测试,无需 GNOME 环境

性能说明

  • 动画只在换行后的时间窗内全速重绘:换行后约 600ms 以 60fps 跑完放大/加亮/滚动,之后立刻回到「只在换字时重绘」的省电模式。逐字歌词静止期约占单核 3%,动画期短暂升高。
  • 没有逐字歌词时使用连续整行擦除,需要按 refresh-interval(默认 16ms)持续重绘,CPU 占用会更高;可在设置中把重绘间隔调大到 50–66ms 换取更低占用。
  • 长行滚动使用临界阻尼插值(每帧 25%),跟随演唱进度平稳移动,不做匀速跑马灯。
  • SSE 短暂断开会保留 3 秒宽限期,避免歌词闪烁。

已知限制

  • 仅支持 GNOME Shell 50 / 51
  • 依赖 GNOME Shell 扩展机制,Shell 大版本升级可能需要适配
  • 不是所有歌都有 lxlyric / tlyric / rlyric,缺失时自动退化为整行进度或隐藏对应行
  • 歌词进度依赖 LX Music 开放 API 推送(约 4Hz),并用单调时钟插值,同步精度约为毫秒级
  • 许可证:GPL-3.0-or-later(见 LICENSE 与 NOTICE)

致谢 / Attribution

  • tuberry/desktop-lyric(GPL-3.0-or-later)—— 本项目的 GNOME Shell 覆盖层绘制思路(St.DrawingArea + Cairo/Pango 透明绘制、锁定/解锁与 Shell.util_set_hidden_from_pick 用法)参考了该项目。
  • LX Music Open API 文档
S
Description
No description provided
Readme GPL-3.0
192 KiB
0 Stars 1 Watchers 0 Forks
Languages
JavaScript 97.7%
Shell 2%
CSS 0.3%