aboutsummaryrefslogtreecommitdiff
path: root/src/dbus
diff options
context:
space:
mode:
Diffstat (limited to 'src/dbus')
-rw-r--r--src/dbus/freedesktop_login1.rs105
-rw-r--r--src/dbus/mod.rs18
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 {