mirror of
https://github.com/niri-wm/niri.git
synced 2026-06-21 02:01:55 +07:00
Add login1 LidClosed monitoring
This commit is contained in:
@@ -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)
|
||||
}
|
||||
@@ -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 {
|
||||
|
||||
+12
@@ -120,6 +120,8 @@ use crate::cursor::{CursorManager, CursorTextureCache, RenderCursor, XCursor};
|
||||
#[cfg(feature = "dbus")]
|
||||
use crate::dbus::freedesktop_locale1::Locale1ToNiri;
|
||||
#[cfg(feature = "dbus")]
|
||||
use crate::dbus::freedesktop_login1::Login1ToNiri;
|
||||
#[cfg(feature = "dbus")]
|
||||
use crate::dbus::gnome_shell_introspect::{self, IntrospectToNiri, NiriToIntrospect};
|
||||
#[cfg(feature = "dbus")]
|
||||
use crate::dbus::gnome_shell_screenshot::{NiriToScreenshot, ScreenshotToNiri};
|
||||
@@ -726,6 +728,8 @@ impl State {
|
||||
self.niri.notified_activity_this_iteration = false;
|
||||
}
|
||||
|
||||
// We monitor both libinput and logind: libinput is always there (including without DBus), but
|
||||
// it misses some switch events (e.g. after unsuspend) on some systems.
|
||||
pub fn set_lid_closed(&mut self, is_closed: bool) {
|
||||
if self.niri.is_lid_closed == is_closed {
|
||||
return;
|
||||
@@ -2298,6 +2302,14 @@ impl State {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "dbus")]
|
||||
pub fn on_login1_msg(&mut self, msg: Login1ToNiri) {
|
||||
let Login1ToNiri::LidClosedChanged(is_closed) = msg;
|
||||
|
||||
trace!("login1 lid {}", if is_closed { "closed" } else { "opened" });
|
||||
self.set_lid_closed(is_closed);
|
||||
}
|
||||
|
||||
#[cfg(feature = "dbus")]
|
||||
pub fn on_locale1_msg(&mut self, msg: Locale1ToNiri) {
|
||||
let Locale1ToNiri::XkbChanged(xkb) = msg;
|
||||
|
||||
Reference in New Issue
Block a user