From f2fc1e948079f195feea6d319be600563a935fc1 Mon Sep 17 00:00:00 2001 From: Victoria Brekenfeld Date: Tue, 29 Jul 2025 15:57:38 +0200 Subject: [PATCH] dbus: Take lid-inhibitor-locks on systemd systems --- Cargo.lock | 11 +++++++++++ Cargo.toml | 3 ++- src/dbus/logind.rs | 17 +++++++++++++++++ src/dbus/mod.rs | 2 ++ src/state.rs | 38 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 70 insertions(+), 1 deletion(-) create mode 100644 src/dbus/logind.rs diff --git a/Cargo.lock b/Cargo.lock index abfe332b..aa67492a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -841,6 +841,7 @@ dependencies = [ "libdisplay-info", "libsystemd", "log-panics", + "logind-zbus", "once_cell", "ordered-float", "parking_lot 0.12.3", @@ -3060,6 +3061,16 @@ dependencies = [ "log", ] +[[package]] +name = "logind-zbus" +version = "5.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "469c962578b549a82f3d0cc72d0f77d1123780fa7121e2b03d78b0780f6ccac6" +dependencies = [ + "serde", + "zbus", +] + [[package]] name = "loom" version = "0.7.2" diff --git a/Cargo.toml b/Cargo.toml index da39726f..229b42d6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -66,6 +66,7 @@ reis = { version = "0.5", features = ["calloop"] } # CLI arguments clap_lex = "0.7" parking_lot = "0.12.3" +logind-zbus = { version = "5.3.2", optional = true } [dependencies.id_tree] branch = "feature/copy_clone" @@ -100,7 +101,7 @@ optional = true [features] debug = ["egui", "egui_plot", "smithay-egui", "anyhow/backtrace"] default = ["systemd"] -systemd = ["libsystemd"] +systemd = ["libsystemd", "logind-zbus"] profile-with-tracy = ["profiling/profile-with-tracy", "tracy-client/default"] [profile.dev.package.tiny-skia] diff --git a/src/dbus/logind.rs b/src/dbus/logind.rs new file mode 100644 index 00000000..75ee9d8d --- /dev/null +++ b/src/dbus/logind.rs @@ -0,0 +1,17 @@ +use std::os::fd::OwnedFd; + +use logind_zbus::manager::{InhibitType::HandleLidSwitch, ManagerProxyBlocking}; +use zbus::blocking::Connection; + +pub fn inhibit_lid() -> anyhow::Result { + let conn = Connection::system()?; + let proxy = ManagerProxyBlocking::new(&conn)?; + let fd = proxy.inhibit( + HandleLidSwitch, + "cosmic-comp", + "External output connected", + "block", + )?; + + Ok(fd.into()) +} diff --git a/src/dbus/mod.rs b/src/dbus/mod.rs index 13b2bcc5..3381eb5a 100644 --- a/src/dbus/mod.rs +++ b/src/dbus/mod.rs @@ -4,6 +4,8 @@ use calloop::{InsertError, LoopHandle, RegistrationToken}; use std::collections::HashMap; use zbus::blocking::{fdo::DBusProxy, Connection}; +#[cfg(feature = "systemd")] +pub mod logind; mod power; pub fn init(evlh: &LoopHandle<'static, State>) -> Result> { diff --git a/src/state.rs b/src/state.rs index e20ac349..3f669e66 100644 --- a/src/state.rs +++ b/src/state.rs @@ -112,6 +112,9 @@ use smithay::{ }; use time::UtcOffset; +#[cfg(feature = "systemd")] +use std::os::fd::OwnedFd; + use std::{ cell::RefCell, cmp::min, @@ -249,6 +252,9 @@ pub struct Common { pub atspi_state: AtspiState, pub atspi_ei: crate::wayland::handlers::atspi::AtspiEiState, + + #[cfg(feature = "systemd")] + inhibit_lid_fd: Option, } #[derive(Debug)] @@ -504,6 +510,7 @@ impl<'a> LockedBackend<'a> { } loop_handle.insert_idle(move |state| { + state.update_inhibitor_locks(); state.common.update_xwayland_scale(); state.common.update_xwayland_primary_output(); }); @@ -707,6 +714,9 @@ impl State { atspi_state, atspi_ei: Default::default(), + + #[cfg(feature = "systemd")] + inhibit_lid_fd: None, }, backend: BackendData::Unset, ready: Once::new(), @@ -726,6 +736,34 @@ impl State { security_context: None, } } + + fn update_inhibitor_locks(&mut self) { + #[cfg(feature = "systemd")] + { + use tracing::{debug, error}; + + let outputs = self.backend.lock().all_outputs(); + let should_handle_lid = outputs.iter().any(|o| o.is_internal()) && outputs.len() >= 2; + + if should_handle_lid { + if self.common.inhibit_lid_fd.is_none() { + match crate::dbus::logind::inhibit_lid() { + Ok(fd) => { + debug!("Inhibiting lid switch"); + self.common.inhibit_lid_fd = Some(fd); + } + Err(err) => { + error!("Failed to inhibit lid switch: {}", err); + } + } + } + } else { + if self.common.inhibit_lid_fd.take().is_some() { + debug!("Removing inhibitor-lock on lid switch") + } + } + } + } } fn primary_scanout_output_compare<'a>(