问题:Linux 托盘依赖链已经断了,而且是静默地断
core/platform/tray_bridge.c 的 Linux 托盘走的是 vendored tray.h(zserge/tray,钉在 2018 年的 commit)的 TRAY_APPINDICATOR 分支,编译期需要 pkg-config 找到 gtk+-3.0 和 appindicator3-0.1,找不到就静默编译成 EUI_TRAY_HAS_BACKEND=0 的 stub。
这条链现在有三个问题:
- libappindicator 已实质停更。社区接手的维护版是 Ayatana fork(libayatana-appindicator),但它的 pkg-config 名是
ayatana-appindicator3-0.1 —— 当前 CMake 只探测旧名 appindicator3-0.1。在只装了 Ayatana 版的新发行版上,探测静默失败,托盘静默变成空壳,用户和应用开发者都无从察觉。
- 依赖链太重,与项目整体的轻量风格(单头文件 vendor、stb/nanosvg/md4c)不符:GTK3 + libappindicator 背后是 cairo/pango/gdk-pixbuf/dbus-glib/libdbusmenu 等一整张网。
- GTK3 本身已进入维护模式,主线是 GTK4。
关键事实:死掉的是库,协议还活着
libappindicator 底层说的协议是 freedesktop 的 StatusNotifierItem(SNI,org.kde.StatusNotifierItem)+ 配套的 DBusMenu(com.canonical.dbusmenu)。这个协议至今是 Linux 托盘的活标准:
- KDE Plasma 原生实现,Frameworks 6 的 KStatusNotifierItem 持续维护;
- GNOME 用户安装的 AppIndicator/KStatusNotifierItem 扩展实现的也是同一个协议——注意:用 libappindicator 的 GNOME 用户本来就必须装这个扩展,所以绕过库直接说协议,覆盖面一分不少;
- Cinnamon、MATE、xfce(带插件)等均有实现;
- 走 D-Bus 消息而非 X11 嵌窗,纯 Wayland 会话下也能工作(老的 XEmbed 托盘在 Wayland 上物理上不可能工作)。
提议:在 tray_bridge.c 加第四个后端 EUI_TRAY_SNI
不引入任何新库,用 GLib 的 GDBus 直接说 SNI + DBusMenu 协议:
- 依赖从整条 GTK 链减到 glib/gio —— glib 在所有桌面 Linux 上必然存在,比"GTK3 + libappindicator 都要恰好装上"可靠得多;
- 体量约 450 行 C:watcher 注册 + SNI 属性/Activate 约 220 行,DBusMenu 服务端约 180 行(现有 bridge 契约只需 Show/Exit 两项,可做静态布局,砍掉动态更新协议),主循环接入约 30 行;
- 失败可优雅降级:session bus 上没有 StatusNotifierWatcher(用户没装任何托盘宿主)时
eui_tray_init 返回失败,行为和今天"没装 dev 包"完全一致,不会引入新的崩溃面;
- 现有 appindicator 路径可保留为 CMake fallback(SNI 优先),也可以直接替换——想听听你的偏好;
- 实现会对照 libayatana-appindicator 的
app-indicator.c 和 jjk-jacky/statusnotifier(都是 C + GDBus 的成熟实现)来写,协议细节(注册时序、ARGB32 图标字节序、menu revision 计数)直接沿用已验证的做法,不重新发明;
- 我会在 KDE Plasma(原生 SNI)和 GNOME + AppIndicator 扩展上各验证一遍图标显示 / Show / Exit,结果贴进 PR。
动机
我在给 EUI-NEO 做 mcpp C++ 包管理索引的打包(compat.eui-neo),索引的 hermetic 构建政策不允许链接宿主系统的 .so,GTK 链无法进入依赖闭包,所以 Linux 托盘在打包版里只能是 stub。绕过 GTK 直接说协议之后,上游普通 CMake 用户和打包生态可以同时受益。
如果你认可这个方向,我可以来提交这个 PR。也想听听你对后端组织方式(新增分支 vs 替换 appindicator)和测试预期的想法。
问题:Linux 托盘依赖链已经断了,而且是静默地断
core/platform/tray_bridge.c的 Linux 托盘走的是 vendoredtray.h(zserge/tray,钉在 2018 年的 commit)的TRAY_APPINDICATOR分支,编译期需要 pkg-config 找到gtk+-3.0和appindicator3-0.1,找不到就静默编译成EUI_TRAY_HAS_BACKEND=0的 stub。这条链现在有三个问题:
ayatana-appindicator3-0.1—— 当前 CMake 只探测旧名appindicator3-0.1。在只装了 Ayatana 版的新发行版上,探测静默失败,托盘静默变成空壳,用户和应用开发者都无从察觉。关键事实:死掉的是库,协议还活着
libappindicator 底层说的协议是 freedesktop 的 StatusNotifierItem(SNI,
org.kde.StatusNotifierItem)+ 配套的 DBusMenu(com.canonical.dbusmenu)。这个协议至今是 Linux 托盘的活标准:提议:在 tray_bridge.c 加第四个后端
EUI_TRAY_SNI不引入任何新库,用 GLib 的 GDBus 直接说 SNI + DBusMenu 协议:
eui_tray_init返回失败,行为和今天"没装 dev 包"完全一致,不会引入新的崩溃面;app-indicator.c和 jjk-jacky/statusnotifier(都是 C + GDBus 的成熟实现)来写,协议细节(注册时序、ARGB32 图标字节序、menu revision 计数)直接沿用已验证的做法,不重新发明;动机
我在给 EUI-NEO 做 mcpp C++ 包管理索引的打包(
compat.eui-neo),索引的 hermetic 构建政策不允许链接宿主系统的.so,GTK 链无法进入依赖闭包,所以 Linux 托盘在打包版里只能是 stub。绕过 GTK 直接说协议之后,上游普通 CMake 用户和打包生态可以同时受益。如果你认可这个方向,我可以来提交这个 PR。也想听听你对后端组织方式(新增分支 vs 替换 appindicator)和测试预期的想法。