diff options
Diffstat (limited to 'src/dbus')
| -rw-r--r-- | src/dbus/freedesktop_login1.rs | 105 | ||||
| -rw-r--r-- | src/dbus/mod.rs | 18 |
2 files changed, 123 insertions, 0 deletions
diff --git a/src/dbus/freedesktop_login1.rs b/src/dbus/freedesktop_login1.rs new file mode 100644 index 00000000..5964d45b --- /dev/null +++ b/src/dbus/freedesktop_login1.rs @@ -0,0 +1,105 @@ +use futures_util::StreamExt; +use zbus::fdo; +use zbus::names::InterfaceName; + +pub enum Login1ToNiri { + LidClosedChanged(bool), +} + +pub fn start( + to_niri: calloop::channel::Sender<Login1ToNiri>, +) -> anyhow::Result<zbus::blocking::Connection> { + let conn = zbus::blocking::Connection::system()?; + + let async_conn = conn.inner().clone(); + let future = async move { + let proxy = fdo::PropertiesProxy::new( + &async_conn, + "org.freedesktop.login1", + "/org/freedesktop/login1", + ) + .await; + let proxy = match proxy { + Ok(x) => x, + Err(err) => { + warn!("error creating PropertiesProxy: {err:?}"); + return; + } + }; + + let mut props_changed = match proxy.receive_properties_changed().await { + Ok(x) => x, + Err(err) => { + warn!("error subscribing to PropertiesChanged: {err:?}"); + return; + } + }; + + let props = proxy + .get_all(InterfaceName::try_from("org.freedesktop.login1.Manager").unwrap()) + .await; + let mut props = match props { + Ok(x) => x, + Err(err) => { + warn!("error receiving initial properties: {err:?}"); + return; + } + }; + + trace!("initial properties: {props:?}"); + + let mut lid_closed = props + .remove("LidClosed") + .and_then(|value| bool::try_from(value).ok()) + .unwrap_or_default(); + + if let Err(err) = to_niri.send(Login1ToNiri::LidClosedChanged(lid_closed)) { + warn!("error sending initial lid state to niri: {err:?}"); + return; + }; + + while let Some(signal) = props_changed.next().await { + let args = match signal.args() { + Ok(args) => args, + Err(err) => { + warn!("error parsing PropertiesChanged args: {err:?}"); + return; + } + }; + + let mut new_lid_closed = lid_closed; + let mut changed = false; + for (name, value) in args.changed_properties() { + trace!("changed property: {name} => {value:?}"); + if *name != "LidClosed" { + continue; + } + + new_lid_closed = bool::try_from(value).unwrap_or(new_lid_closed); + changed = true; + } + + if !changed { + continue; + } + + if new_lid_closed == lid_closed { + continue; + } + + lid_closed = new_lid_closed; + if let Err(err) = to_niri.send(Login1ToNiri::LidClosedChanged(lid_closed)) { + warn!("error sending message to niri: {err:?}"); + return; + }; + } + }; + + let task = conn + .inner() + .executor() + .spawn(future, "monitor login1 property changes"); + task.detach(); + + Ok(conn) +} diff --git a/src/dbus/mod.rs b/src/dbus/mod.rs index 6a164d48..5941456f 100644 --- a/src/dbus/mod.rs +++ b/src/dbus/mod.rs @@ -5,6 +5,7 @@ use crate::niri::State; pub mod freedesktop_a11y; pub mod freedesktop_locale1; +pub mod freedesktop_login1; pub mod freedesktop_screensaver; pub mod gnome_shell_introspect; pub mod gnome_shell_screenshot; @@ -35,6 +36,7 @@ pub struct DBusServers { pub conn_introspect: Option<Connection>, #[cfg(feature = "xdp-gnome-screencast")] pub conn_screen_cast: Option<Connection>, + pub conn_login1: Option<Connection>, pub conn_locale1: Option<Connection>, pub conn_keyboard_monitor: Option<Connection>, } @@ -136,6 +138,22 @@ impl DBusServers { } } + let (to_niri, from_login1) = calloop::channel::channel(); + niri.event_loop + .insert_source(from_login1, move |event, _, state| match event { + calloop::channel::Event::Msg(msg) => state.on_login1_msg(msg), + calloop::channel::Event::Closed => (), + }) + .unwrap(); + match freedesktop_login1::start(to_niri) { + Ok(conn) => { + dbus.conn_login1 = Some(conn); + } + Err(err) => { + warn!("error starting login1 watcher: {err:?}"); + } + } + let (to_niri, from_locale1) = calloop::channel::channel(); niri.event_loop .insert_source(from_locale1, move |event, _, state| match event { |
