我使用 ArchLinux,但这应该是无关紧要的,除了我经常参考它的 wiki 页面的原因之外。
我认为对通知如何工作以及“玩家”如何交互以使通知发挥作用并没有真正清楚的了解:
- 有多少玩家参与其中?
- 什么是通知服务器,它的作用是什么?
- 什么是通知客户端,它有什么作用?
notify-send
我可以用这个东西来弹出通知吗?是(好吧,一个)客户端吗?- 什么是通知守护进程?
- 以及 的作用是什么
libnotify
?
为了理解这一点并在我的系统上设置通知,我参考了这个 wiki 页面。
我先尝试过notification-daemon
。仅安装后这并不起作用。为了使调用notify-send
成功,必须手动启动它(这意味着执行),以某种方式自动启动它,或者使用此内容/usr/lib/notification-daemon-1.0/notification-daemon
创建一个文件/usr/share/dbus-1/services/org.freedesktop.Notifications.service
[D-BUS Service]
Name=org.freedesktop.Notifications
Exec=/usr/lib/notification-daemon-1.0/notification-daemon
然后我尝试了dunst
,但是,一旦安装,就可以正常工作,从某种意义上说,可以notify-send
正常工作。我认为这从根本上来说是因为它在第一次调用时就启动了notify-send
(这意味着我最初的印象是它在我卸载它之后也能工作;那是因为该dunst
进程正在运行),但它是如何做到这一点的呢?
这两个 和notification-daemon
都位于“通知服务器 > 独立”dunst
部分下,但它们也称为“通知守护程序”;这是否意味着通知守护程序和通知服务器是同义词?如果不是,区别在哪里?
从用户(我)的角度来看,这两种美学之间有区别吗?我的意思是,当一个正在运行与另一个正在运行时,我发现通知看起来不同。顺便说一句,这里出现了“他们在提供什么服务?”的问题,因为在我看来,他们只是在等待其他工具向他们发送通知,以便他们可以以良好的方式展示它们。或者他们俩都做这两件事?无论哪种情况,通知最初来自哪里?他们如何到达通知框?
不管怎样,如果我想对通知进行自定义操作怎么办?假设我想获取所有这些内容并拥有自己的 shell 脚本,只需将它们附加到一个文件中~/notifications
。这是否意味着我正在编写自己的通知服务器?还是客户?或者是什么?
我问的原因是我想尝试一下可以在xmobar
状态栏中显示通知的想法(我与 XMonad 窗口管理器一起使用),所以我试图理解所有的部分。
我还看了一下statnot
它看起来非常非常瘦并且没有多余的装饰,但是参考我的上一段,感觉使用statnot
仍然意味着我仍然需要编写一个配置,通过函数update_text
调用xmobar 或 xmonad 公开的一些 API。这样我就无法控制,比如说,我想一次显示多少个通知。
我有点迷失了:/
试图从桌面通知规范中理解我的这个问题的含义并没有成功:D
用一般术语来说,服务器是客户端以某种方式(无论是通过网络还是通过本地 IPC 机制)连接的程序。因此,通知服务器是一个接受来自客户端的“显示通知”请求并代表它们显示通知的程序。
任何使用通知服务器的程序都成为“通知客户端”。这又不是特定于通知的术语;这是关于总体架构的。
是的,在本例中是客户。它的目的主要是为了让你可以弹出通知;应用程序不运行它,因为它们可以直接在自己的进程中执行相同的操作。
与通知服务器完全相同。
术语“守护进程”有一些不同的含义。它指的是任何类型的后台服务,无论它是否是“服务器” - 但在这种情况下,负责显示实际通知弹出窗口的程序同时是服务器和守护程序(因为它运行在像守护进程一样后台,并像服务一样接受请求)。
它是一个小型库,可供通知客户端使用,以抽象出正在使用的 IPC 机制的细节(以及协议版本之间的差异)。该程序不需要了解 D-Bus 和接口,只需了解即可
notify_notification_new(...)
。(也就是说,许多应用程序选择直接实现通信,例如使用 libdbus 进行必要的调用 - 这是一个非常简单的协议,因此这两个选项可能同样常见。)
客户端(如 libnotify)和通知服务器之间使用的协议也经常被误称为“libnotify 协议”。
这就是字面上的区别。这个想法是每个桌面环境(GNOME、KDE 等)都有自己的通知服务器,该服务器将显示针对该桌面环境定制的弹出窗口 - 外观、设置、行为等。
(它甚至不一定是一个单独的守护进程;例如,在 GNOME 和 AwesomeWM 中,通知服务由桌面 shell 本身提供。)
是的,但是“等待其他工具向他们发送通知”才算“提供”某些东西。服务不一定要返回一些数据——任何系统中都有大量服务或多或少是单向的,即它们的工作是做某事而不是返回某事。
如果它实现了通知协议,即客户端与之通信的商定方法,那么您将编写自己的“通知服务器”。对于大多数 Linux 系统来说,事实上的标准是通过 D-Bus 实现“org.freedesktop.Notifications”接口——如果你实现了它,你就拥有了一个通知服务器。
(虽然通过 shell 脚本来做到这一点确实很困难,但考虑到该接口由大约两个函数组成,大约 10 行 Python 或 Perl 就可以完成。)
故意不存在此文件,因为这意味着只有一个程序提供此特定服务 - 而实际上,一个程序可能安装了多个桌面环境,每个桌面环境都有自己的通知服务,并且 D-Bus 没有机制来区分一个程序的优先级实施或其他。
因此,虽然许多其他 D-Bus 服务是可自动启动的,但大多数通知服务器故意不是自动启动的,这样它们就不会被选择在“错误”的桌面环境中启动。桌面环境旨在“手动”启动适当的服务,例如,
~/.xinitrc
如果您这样做,则可以从您的服务启动它。它使用与上面描述的完全相同的方法 - 它的包实际上包含一个 D-Bus .service 文件:
唯一的区别是实际文件不是以其应该提供的服务命名的(dbus-daemon 不会对“用户”服务强制执行此要求)。
这似乎是不可避免的。如果您想要自定义逻辑,那么您需要编写自定义逻辑。
例如,我曾经编写过一个使用 dzen2作为“弹出窗口”的通知守护进程。您可以在 Notify() 方法中实现您喜欢的任何逻辑。
从技术上讲(与实现无关),您至少需要一个处理通知(例如接收和处理它们)的守护进程,一种其他进程将通知移交给所述守护进程的方法,以及关于通知内容的协议(例如标准)从应用程序传递到守护程序的数据看起来像是可以进行处理的。
要填补大多数 Linux 桌面环境的空白:
简而言之,Libnotify 是一个库,提供将符合桌面通知规范的通知发送到也符合此标准的通知守护程序的功能。如果您正在构建一个应支持 Linux 上的桌面通知的应用程序,您可以使用 libnotify 来实现这一点。