7 月 29 日消息 优麒麟官方今天带来了任务栏新版托盘协议(SNI)介绍。
在 Linux 操作系统中,“系统托盘区域”是在给定的 X 屏幕上运行的应用程序,可以显示正在运行的应用程序提供的小图标。系统托盘是一个 X 客户端,在给定的屏幕上拥有一个特殊的管理器选择并提供了容器窗口。Windows 将此功能称为“通知区域”,旧版托盘协议就是通过 X 服务直接获取应用信息,在开发上难度很大。
新版托盘规范定义了可视项的管理,通常是用于向用户报告应用程序状态或提供对该应用程序执行的常见操作的快速访问的图标。它旨在作为 Freedesktop 的桌面通知规范的补充但不直接相关,旨在替代 Freedesktop 系统托盘规范,更加面向模型视图,为工作区提供更多自由,如何以图形方式表示与它的视觉风格语言,这种方式(SNI)是将 systemtray 的调用封装进 dbus 总线中,提升了开发者的开发效率。
从用户角度来看新版托盘协议(SNI)从表面上看不出有什么太大的变化,在开发的角度上是将最上层的应用与下层基础库的分离。
实现方式
新版托盘协议主要是通过三个库来实现的:
dbusmenu 是实现应用程序和面板(#5)之间传输协议的库。dbusmenu 已经被用于开发会话菜单,并且也是在 Lucid 中实现一些新系统菜单的构建块。
indicator-applet 是将托管应用程序指示器区域的面板小程序。指示器小程序是作为消息菜单项目的一部分开发的,旨在成为面板指示器的通用容器 。libappindicator 是一个新的库,用于帮助应用程序端更改;它确实注册了图标和菜单,并在内部使用 dbusmenu 通过 dbus 发布上下文菜单。虽然它是 Gnome 桌面的新库,但它基于在 KDE 项目中设计的用于更新系统托盘协议的协议(上面的“信令协议”部分)。libappindicator 采用并扩展了该协议,并将其与 dbusmenu 连接以提供应用程序迁移其代码所需的全套服务 。
SNI 工作流程
3.1 托盘应用托盘封装
通过 dbusmenu,indicator-applet,libappindicator 将托盘应用的属性,方法,以及信号注册到 dbus 总线上,在任务栏上进行 dbus 监听解析来实现与托盘应用交互。
注册 item 的方法有:
属性有:
信号有:
3.2 注册 dbus 服务
当拿到了托盘应用的信息然后就需要对信息进行封装通过 dbus 的方式发送给任务栏,在任务栏上会注册一个 statusnotifierWatcher 的服务用来检测托盘信息的,每当托盘应用打开的时候都会调用 statusnotifierWatcher 的 RegisterStatusNotifierItem 方法在任务栏的托盘区域进行按钮的注册,当托盘应用关闭的时候会调用任务栏 unRegisterStatusNotifierItem 方法来取消在任务栏上的注册。
3.3 调用 dbus 的方法
当用户对托盘应用进行操作的时候,会调用相应 dbus 方法,并激活相关事件。例如左键点击会触发“激活窗口”的事件,右键单击会触发“显示右键菜单”的事件,悬浮会触发“显示提示语”的事件
SNI 协议使用的方式
4.1 注册 statusnotifierHost 的 dbus
在一个桌面上为了防止托盘应用会在多个地方注册成托盘,用一个 dbus 来让托盘应用只能注册到一个托盘来确保不会出现功能上不稳定。
4.2 注册 statusnotifierWatch 的 dbus
用来检测托盘应用的打开和关闭,statusnotifierWatch 的 RegisterStatusNotifierItem 和 unRegisterStatusNotifierItem 是协议层与应用层来进行交互的信号,通过 RegisterStatusNotifierItem 方法来获取应用注册的 dbus 的服务名。
4.3 对托盘应用的 dbus 进行调用
上文说的鼠标事件点击调用槽函数是一部分,还可以监听托盘应用的 signal 如图标变换,提示信息变化等。如果需要托盘应用的窗口以及其他属性,还可以通过 dbus 来获取 properties。
4.4 在优麒麟桌面环境下使用
Qt 应用程序可以在自己的应用程序里创建一个 QSystemtrayIcon 类,并为这个类似设置图标和事件槽函数,在任务栏上会自动生成托盘图标。
Gtk 程序通过
来注册应用为托盘应用,即可实现在任务栏上显示托盘图标。
注意事项
5.1 在 dbus 调用的时候可能会出现延时,必要的话可以考虑多线程处理,避免界面阻塞。
5.2 由于 dbus 调用是异步调用出现响应慢问题,在读取托盘应用信息是可能会需要添加延时读取,不然会出现信息读取不到的地方。