Skip to content

Linux 托盘方案提议:绕过已停更的 libappindicator 依赖链,用 GDBus 直接实现 StatusNotifierItem #58

Description

@FarnaHerry

问题:Linux 托盘依赖链已经断了,而且是静默地断

core/platform/tray_bridge.c 的 Linux 托盘走的是 vendored tray.h(zserge/tray,钉在 2018 年的 commit)的 TRAY_APPINDICATOR 分支,编译期需要 pkg-config 找到 gtk+-3.0appindicator3-0.1,找不到就静默编译成 EUI_TRAY_HAS_BACKEND=0 的 stub。

这条链现在有三个问题:

  1. libappindicator 已实质停更。社区接手的维护版是 Ayatana fork(libayatana-appindicator),但它的 pkg-config 名是 ayatana-appindicator3-0.1 —— 当前 CMake 只探测旧名 appindicator3-0.1。在只装了 Ayatana 版的新发行版上,探测静默失败,托盘静默变成空壳,用户和应用开发者都无从察觉
  2. 依赖链太重,与项目整体的轻量风格(单头文件 vendor、stb/nanosvg/md4c)不符:GTK3 + libappindicator 背后是 cairo/pango/gdk-pixbuf/dbus-glib/libdbusmenu 等一整张网。
  3. 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)和测试预期的想法。

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions