Port all dbus server/client to to zbus

Seems to generally be working well. May still need a few fixes.
This commit is contained in:
Ian Douglas Scott 2021-12-10 16:32:17 -08:00 committed by Ian Douglas Scott
parent 8b5e1a7f12
commit 8b2a9c6359
13 changed files with 592 additions and 821 deletions

View file

@ -1,106 +1,70 @@
use gtk4::{
gio,
glib::{self, clone},
prelude::*,
};
#![allow(non_snake_case)]
use std::sync::{Arc, Mutex};
use zbus::{dbus_interface, MessageHeader, Result, SignalContext};
static STATUS_NOTIFIER_XML: &str = "
<node name='/StatusNotifierWatcher'>
<interface name='org.kde.StatusNotifierWatcher'>
<method name='RegisterStatusNotifierItem'>
<arg name='service' type='s' direction='in' />
</method>
use crate::dbus_service;
<method name='RegisterStatusNotifierHost'>
<arg name='service' type='s' direction='in' />
</method>
<property name='RegisteredStatusNotifierItems' type='as' access='read' />
<property name='IsStatusNotifierHostRegistered' type='b' access='read' />
<property name='ProtocolVersion' type='i' access='read' />
<signal name='StatusNotifierItemRegistered'>
<arg type='s' name='service' direction='out' />
</signal>
<signal name='StatusNotifierItemUnregistered'>
<arg type='s' name='service' direction='out' />
</signal>
<signal name='StatusNotifierHostRegistered' />
<signal name='StatusNotifierHostUnregistered' />
</interface>
</node>
";
pub fn start() {
gio::bus_own_name(
gio::BusType::Session,
"org.kde.StatusNotifierWatcher",
gio::BusNameOwnerFlags::NONE,
bus_acquired,
name_acquired,
name_lost,
);
#[derive(Default)]
struct StatusNotifierWatcher {
items: Arc<Mutex<Vec<String>>>,
}
fn bus_acquired(_connection: gio::DBusConnection, _name: &str) {}
fn name_acquired(connection: gio::DBusConnection, _name: &str) {
let introspection_data = gio::DBusNodeInfo::for_xml(STATUS_NOTIFIER_XML).unwrap();
let interface_info = introspection_data
.lookup_interface("org.kde.StatusNotifierWatcher")
.unwrap();
let items = Arc::new(Mutex::new(Vec::<String>::new()));
let method_call = clone!(@strong items => move |connection: gio::DBusConnection,
sender: &str,
path: &str,
interface: &str,
method: &str,
args: glib::Variant,
invocation: gio::DBusMethodInvocation| {
match method {
"RegisterStatusNotifierItem" => {
let (service,) = args.get::<(String,)>().unwrap();
let service = format!("{}{}", sender, service);
connection.emit_signal(None, path, interface, "StatusNotifierItemRegistered", Some(&(&service,).to_variant())).unwrap();
// XXX emit unreigstered
items.lock().unwrap().push(service);
invocation.return_value(None);
}
"RegisterStatusNotifierHost" => {
let (_service,) = args.get::<(String,)>().unwrap();
// XXX emit registed/unregistered
invocation.return_value(None);
}
_ => unreachable!()
}
});
let get_property = clone!(@strong items => move |_: gio::DBusConnection, _sender: &str, _path: &str, _interface: &str, prop: &str| {
match prop {
"RegisteredStatusNotifierItems" => items.lock().unwrap().to_variant(),
"IsStatusNotifierHostRegistered" => true.to_variant(),
"ProtocolVersion" => 0i32.to_variant(),
_ => unreachable!(),
}
});
let set_property = |_: gio::DBusConnection,
_sender: &str,
_path: &str,
_interface: &str,
_prop: &str,
_value: glib::Variant| { unreachable!() };
if let Err(err) = connection.register_object(
"/StatusNotifierWatcher",
&interface_info,
method_call,
get_property,
set_property,
#[dbus_interface(name = "org.kde.StatusNotifierWatcher")]
impl StatusNotifierWatcher {
async fn RegisterStatusNotifierItem(
&self,
service: &str,
#[zbus(header)] hdr: MessageHeader<'_>,
#[zbus(signal_context)] ctxt: SignalContext<'_>,
) {
eprintln!("Failed to register object: {}", err);
let service = format!("{}{}", hdr.sender().unwrap().unwrap(), service);
Self::StatusNotifierItemRegistered(&ctxt, &service)
.await
.unwrap();
// XXX emit unreigstered
self.items.lock().unwrap().push(service);
}
fn RegisterStatusNotifierHost(&self, _service: &str) {
// XXX emit registed/unregistered
}
#[dbus_interface(property)]
fn RegisteredStatusNotifierItems(&self) -> Vec<String> {
self.items.lock().unwrap().clone()
}
#[dbus_interface(property)]
fn IsStatusNotifierHostRegistered(&self) -> bool {
true
}
#[dbus_interface(property)]
fn ProtocolVersion(&self) -> i32 {
0
}
#[dbus_interface(signal)]
async fn StatusNotifierItemRegistered(ctxt: &SignalContext<'_>, service: &str) -> Result<()>;
#[dbus_interface(signal)]
async fn StatusNotifierItemUnregistered(ctxt: &SignalContext<'_>, service: &str) -> Result<()>;
#[dbus_interface(signal)]
async fn StatusNotifierHostRegistered(ctxt: &SignalContext<'_>) -> Result<()>;
#[dbus_interface(signal)]
async fn StatusNotifierHostUnregistered(ctxt: &SignalContext<'_>) -> Result<()>;
}
pub async fn start() {
if let Err(err) = dbus_service::create("org.kde.StatusNotifierWatcher", |builder| {
builder.serve_at("/StatusNotifierWatcher", StatusNotifierWatcher::default())
})
.await
{
eprintln!("Failed to start `StatusNotifierWatcher` service: {}", err);
}
}
fn name_lost(_connection: Option<gio::DBusConnection>, _name: &str) {}