diff --git a/src/main.rs b/src/main.rs index 8e67564a..0f275970 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,6 +5,7 @@ mod mpris; mod mpris_player; mod status_area; mod status_menu; +mod status_notifier_watcher; mod time_button; mod window; mod x; @@ -37,5 +38,7 @@ fn main() { } }); + status_notifier_watcher::start(); + glib::MainLoop::new(None, false).run(); } diff --git a/src/status_notifier_watcher.rs b/src/status_notifier_watcher.rs new file mode 100644 index 00000000..eab00d7a --- /dev/null +++ b/src/status_notifier_watcher.rs @@ -0,0 +1,104 @@ +use gtk4::{ + gio, + glib::{self, clone}, + prelude::*, +}; +use std::sync::{Arc, Mutex}; + +static STATUS_NOTIFIER_XML: &str = " + + + + + + + + + + + + + + + + + + + + + + + + + + + +"; + +pub fn start() { + // XXX flags? + 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(); + connection.emit_signal(None, path, interface, "StatusNotifierItemRegistered", Some(&(&service,).to_variant())).unwrap(); + // XXX emit unreigstered + items.lock().unwrap().push(service); + } + "RegisterStatusNotifierHost" => { + let (_service,) = args.get::<(String,)>().unwrap(); + // XXX emit registed/unregistered + } + _ => unreachable!() + } + invocation.return_dbus_error("DBus.Error.UnknownMethod", "Unknown method"); + }); + 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) {}