feat(linux): 新增基于 GDBus 的 StatusNotifierItem 托盘后端,替代失效的 libappindicator 链条 - #59
Open
FarnaHerry wants to merge 3 commits into
Open
feat(linux): 新增基于 GDBus 的 StatusNotifierItem 托盘后端,替代失效的 libappindicator 链条#59FarnaHerry wants to merge 3 commits into
FarnaHerry wants to merge 3 commits into
Conversation
The existing Linux tray path depends on GTK3 + libappindicator, whose upstream is unmaintained and whose Ayatana fork renamed the pkg-config module, so tray support silently breaks on modern distributions. Add an EUI_TRAY_SNI backend that speaks the freedesktop StatusNotifierItem and com.canonical.dbusmenu protocols directly over GDBus, needing only glib/gio -- present on every desktop Linux. The SNI branch is preferred when gio-2.0 is found; the GTK3 + libappindicator chain remains as a fallback. The backend exports org.kde.StatusNotifierItem (Activate / scroll / secondary-activate) and a DBusMenu server with Show / Exit items, and registers with org.kde.StatusNotifierWatcher. Verified end-to-end on a KDE Plasma session bus: watcher registration, Activate, menu Event dispatch and GetLayout (Show / separator / Exit) all confirmed via cross-process gdbus calls.
…ssing Follow-up to the review on issue sudoevolve#58: - xmake.lua gains the same Linux tray wiring as CMake: a new tray option (default on), pkg-config detection of gio-2.0 (SNI, preferred) and appindicator3-0.1 (legacy fallback), with the define and link flags applied in on_load (package detection is script-scope only). - Both build systems now stop configuration with a clear error when no tray backend dependency is found, instead of silently compiling the empty EUI_TRAY_HAS_BACKEND=0 stub. Opt out with -DEUI_ENABLE_TRAY=OFF or --tray=n. - The SNI branch remains additive: appindicator builds are untouched and still selected when glib is absent but the old stack is present. Verified locally: CMake + xmake, each with (a) glib present -> SNI define + link, (b) no tray deps -> clear configure error, (c) tray disabled -> stub builds fine.
Contributor
Author
|
按 #58 的 review 意见逐条对齐了,见追加提交 134a8af:
两个构建系统的三种场景(有 glib / 无依赖报错 / 关闭 tray 出 stub)都在本地逐一验证过。 |
…bbing eui_begin/end_quiet_third_party_config replaces PKG_CONFIG_EXECUTABLE with a stub and FORCE-restores the previous (usually empty) value into the cache. That poisoned cache entry made find_package(PkgConfig) fail for the tray probes below, so CI runners (which have both pkg-config and libglib2.0-dev) hit the new "no tray backend" FATAL_ERROR. Local builds never saw it because they passed -DPKG_CONFIG_EXECUTABLE explicitly. Drop the poisoned cache entry before find_package(PkgConfig) so the tray probes see the real pkg-config. The bundled third-party scopes are unaffected: they install the stub themselves inside their own scope.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
概述
为 Linux 平台新增一个基于 StatusNotifierItem(SNI)协议 的托盘后端,只依赖 glib/gio(GDBus),用来替代目前已经事实失效的 GTK3 + libappindicator 兼容链条。
背景与动机
当前 Linux 托盘走的是
GTK3 + libappindicator链条,存在两个现实问题:appindicator3-0.1改成了ayatana-appindicator3-0.1。3rd/dependencies.cmake里探测的是旧名字,所以在只装 Ayatana 版本的发行版上探测直接失败,托盘被静默禁用。既然 SNI 是纯 D-Bus 协议,而 glib/gio 在任何桌面 Linux 上都必然存在(连最小容器镜像都常带),完全可以不经过任何中间库直接讲这个协议。
实现内容
core/platform/tray_bridge.c新增EUI_TRAY_SNI分支(插在 appindicator 分支之前),用纯 GDBus 实现协议要求的全部表面:org.kde.StatusNotifierItem(/路径下的 item 对象):Id / Title / IconName / IconThemePath / Status / Menu 等只读属性,以及 Activate / SecondaryActivate / Scroll 方法。Activate置位g_show_requested,与既有eui_tray_consume_show_requested()公共契约对接,对外 API 零改动。com.canonical.dbusmenu(/org/freedesktop/DBusMenu):GetLayout / GetGroupProperties / GetProperty / Event / EventGroup / AboutToShow( Group)方法,提供 Show / 分隔符 / Exit 三个菜单项,点击经Event(clicked)分别置位 show / exit 标志。org.kde.StatusNotifierWatcher.RegisterStatusNotifierItem,并在 watcher 重启时自动重新注册。公开头文件
tray_bridge.h未做任何修改。CMake 依赖链条改动与影响面论证
改动只有两处,且都是纯增量,不删除任何既有探测:
3rd/dependencies.cmake:在既有pkg_check_modules(EUI_APPINDICATOR ...)/EUI_GTK3之前,新增一行QUIET:glib 不存在时 configure 不报错、不警告,与 appindicator 探测的行为完全一致,不构成新的硬性构建依赖。gobject-2.0显式列出:正常情况下由gio-2.0.pc的Requires自动带入,显式写出可保证链接行在被裁剪过的 .pc 环境(如部分交叉 sysroot)下依然完整。CMakeLists.txt平台分支:在elseif(UNIX AND EUI_APPINDICATOR_FOUND AND EUI_GTK3_FOUND)之前插入elseif(UNIX AND EUI_GIO_FOUND)分支,原 appindicator 分支原样保留:影响面分析(基于全仓库 grep):
EUI_GIO_FOUND为假,控制流落到与改动前完全相同的位置eui_tray_*契约,上层无感EUI_TRAY_*宏在全仓库仅有两个消费方:CMakeLists.txt(定义)与core/platform/tray_bridge.c(#if/#elif实现),没有任何其他源文件按平台分支处理托盘,因此不存在隐藏的联动改动。EUI_GIO_*/EUI_APPINDICATOR_*/EUI_GTK3_*变量同样只在上述两个 cmake 文件中使用,不影响其他第三方依赖的探测顺序与结果。测试与验证
在 Fedora 44 / KDE Plasma(glib 2.88)上完成三层验证:
tray_bridge.c(-DEUI_TRAY_SNI=1),在真实 session bus 上断言——init 成功、item 出现在 watcher 的RegisteredStatusNotifierItems、跨连接模拟Activate与菜单Event(Show/Exit)均能翻转对应 consume 标志、GetLayout返回结构完整的(u(ia{sv}av))、shutdown 干净注销,全部通过。gdbusCLI 从独立进程调用,GetLayout实际字节流为GetGroupProperties/GetProperty/AboutToShow返回亦符合 DBusMenu 规范。EUI_TRAY_SNI=1正确进入编译定义,tray_bridge.c无警告通过,最终可执行文件仅 NEEDEDlibgio-2.0/libgobject-2.0/libglib-2.0,无任何 GTK/appindicator 依赖。GTK3 + appindicator 分支的代码路径未做任何修改,其既有行为(在仍提供旧栈的系统上)保持不变。
更新:按 review 意见补齐(2026-08-13)
针对 #58 的 review 反馈,追加提交
134a8af:xmake.lua新增tray选项(默认开),Linux 下通过on_load里的find_package("pkgconfig::gio-2.0")探测(描述作用域拿不到包探测 API,故放脚本作用域),gio 优先、appindicator3-0.1兜底,与 CMake 行为完全一致。此前 xmake 在 Linux 上不定义任何托盘宏,只会产出 stub。-DEUI_ENABLE_TRAY=OFF可关闭)与 xmake(--tray=n)现在在没有任何可用托盘依赖时直接终止 configure 并给出安装提示,不再静默产出EUI_TRAY_HAS_BACKEND=0的空壳。两个构建系统各自验证三种场景:有 glib → SNI 宏+链接正确;无依赖 → 明确报错;关闭 tray → stub 正常编译。
验证状态
gdbus线路验证外,另用一个完整的 EUI 应用(窗口+按钮,DSL 开.tray(true))实机验证:托盘图标显示、窗口关闭最小化到托盘、托盘 Show 恢复窗口、Exit 正常退出,全部正常。