use std::time::Duration; use anyhow::Context; use dbus::{ Message, arg::{PropMap, Variant}, blocking::Connection, channel::MatchingReceiver, message::MatchRule, }; use crate::subsystem::dbus::{ fcitx5::OrgFcitxFcitxController1, notifications::OrgFreedesktopNotifications, }; mod fcitx5; mod notifications; pub type DbusReceiveCallback = Box bool + Send>; pub type DbusMatchCallback = Box bool + Send>; #[derive(Default)] pub struct DbusConnector { pub connection: Option, } impl DbusConnector { pub fn tick(&self) { if let Some(c) = self.connection.as_ref() { let _ = c.process(Duration::ZERO); } } pub fn become_monitor( &mut self, rule: MatchRule<'static>, callback: DbusReceiveCallback, ) -> anyhow::Result<()> { let connection = self .connection .take() .context("Not connected") .or_else(|_| Connection::new_session())?; let proxy = connection.with_proxy( "org.freedesktop.DBus", "/org/freedesktop/DBus", Duration::from_millis(5000), ); let result: Result<(), dbus::Error> = proxy.method_call( "org.freedesktop.DBus.Monitoring", "BecomeMonitor", (vec![rule.match_str()], 0u32), ); result?; let _ = connection.start_receive(rule, callback); self.connection = Some(connection); Ok(()) } pub fn add_match( &mut self, rule: MatchRule<'static>, callback: DbusMatchCallback, ) -> anyhow::Result<()> { let connection = self .connection .take() .context("Not connected") .or_else(|_| Connection::new_session())?; let _ = connection.add_match(rule, callback)?; self.connection = Some(connection); Ok(()) } pub fn fcitx_keymap() -> anyhow::Result { let connection = Connection::new_session()?; let proxy = connection.with_proxy( "org.fcitx.Fcitx5", "/controller", Duration::from_millis(500), ); proxy .current_input_method() .context("Could not get D-Bus response") } pub fn notify_send( summary: &str, body: &str, urgency: u8, timeout: i32, replaces_id: u32, transient: bool, ) -> anyhow::Result { let connection = Connection::new_session()?; let proxy = connection.with_proxy( "org.freedesktop.Notifications", "/org/freedesktop/Notifications", Duration::from_millis(500), ); let mut hints = PropMap::new(); hints.insert("urgency".to_string(), Variant(Box::new(urgency))); hints.insert("transient".to_string(), Variant(Box::new(transient))); let retval = proxy.notify( "WlxOverlay-S", replaces_id, "", summary, body, vec![], hints, timeout, )?; Ok(retval) } pub fn notify_close(id: u32) -> anyhow::Result<()> { let connection = Connection::new_session()?; let proxy = connection.with_proxy( "org.freedesktop.Notifications", "/org/freedesktop/Notifications", Duration::from_millis(500), ); proxy.close_notification(id)?; Ok(()) } }