use gtk4::{ gio, glib::{self, clone}, prelude::*, }; use std::sync::{Arc, Mutex}; static STATUS_NOTIFIER_XML: &str = " "; pub fn start() { gio::bus_own_name( gio::BusType::Session, "org.kde.StatusNotifierWatcher", gio::BusNameOwnerFlags::NONE, bus_acquired, name_acquired, name_lost, ); } 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::::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, ) { eprintln!("Failed to register object: {}", err); } } fn name_lost(_connection: Option, _name: &str) {}