dbus: Take lid-inhibitor-locks on systemd systems

This commit is contained in:
Victoria Brekenfeld 2025-07-29 15:57:38 +02:00 committed by Victoria Brekenfeld
parent 8648d4450e
commit f2fc1e9480
5 changed files with 70 additions and 1 deletions

11
Cargo.lock generated
View file

@ -841,6 +841,7 @@ dependencies = [
"libdisplay-info", "libdisplay-info",
"libsystemd", "libsystemd",
"log-panics", "log-panics",
"logind-zbus",
"once_cell", "once_cell",
"ordered-float", "ordered-float",
"parking_lot 0.12.3", "parking_lot 0.12.3",
@ -3060,6 +3061,16 @@ dependencies = [
"log", "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]] [[package]]
name = "loom" name = "loom"
version = "0.7.2" version = "0.7.2"

View file

@ -66,6 +66,7 @@ reis = { version = "0.5", features = ["calloop"] }
# CLI arguments # CLI arguments
clap_lex = "0.7" clap_lex = "0.7"
parking_lot = "0.12.3" parking_lot = "0.12.3"
logind-zbus = { version = "5.3.2", optional = true }
[dependencies.id_tree] [dependencies.id_tree]
branch = "feature/copy_clone" branch = "feature/copy_clone"
@ -100,7 +101,7 @@ optional = true
[features] [features]
debug = ["egui", "egui_plot", "smithay-egui", "anyhow/backtrace"] debug = ["egui", "egui_plot", "smithay-egui", "anyhow/backtrace"]
default = ["systemd"] default = ["systemd"]
systemd = ["libsystemd"] systemd = ["libsystemd", "logind-zbus"]
profile-with-tracy = ["profiling/profile-with-tracy", "tracy-client/default"] profile-with-tracy = ["profiling/profile-with-tracy", "tracy-client/default"]
[profile.dev.package.tiny-skia] [profile.dev.package.tiny-skia]

17
src/dbus/logind.rs Normal file
View file

@ -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<OwnedFd> {
let conn = Connection::system()?;
let proxy = ManagerProxyBlocking::new(&conn)?;
let fd = proxy.inhibit(
HandleLidSwitch,
"cosmic-comp",
"External output connected",
"block",
)?;
Ok(fd.into())
}

View file

@ -4,6 +4,8 @@ use calloop::{InsertError, LoopHandle, RegistrationToken};
use std::collections::HashMap; use std::collections::HashMap;
use zbus::blocking::{fdo::DBusProxy, Connection}; use zbus::blocking::{fdo::DBusProxy, Connection};
#[cfg(feature = "systemd")]
pub mod logind;
mod power; mod power;
pub fn init(evlh: &LoopHandle<'static, State>) -> Result<Vec<RegistrationToken>> { pub fn init(evlh: &LoopHandle<'static, State>) -> Result<Vec<RegistrationToken>> {

View file

@ -112,6 +112,9 @@ use smithay::{
}; };
use time::UtcOffset; use time::UtcOffset;
#[cfg(feature = "systemd")]
use std::os::fd::OwnedFd;
use std::{ use std::{
cell::RefCell, cell::RefCell,
cmp::min, cmp::min,
@ -249,6 +252,9 @@ pub struct Common {
pub atspi_state: AtspiState, pub atspi_state: AtspiState,
pub atspi_ei: crate::wayland::handlers::atspi::AtspiEiState, pub atspi_ei: crate::wayland::handlers::atspi::AtspiEiState,
#[cfg(feature = "systemd")]
inhibit_lid_fd: Option<OwnedFd>,
} }
#[derive(Debug)] #[derive(Debug)]
@ -504,6 +510,7 @@ impl<'a> LockedBackend<'a> {
} }
loop_handle.insert_idle(move |state| { loop_handle.insert_idle(move |state| {
state.update_inhibitor_locks();
state.common.update_xwayland_scale(); state.common.update_xwayland_scale();
state.common.update_xwayland_primary_output(); state.common.update_xwayland_primary_output();
}); });
@ -707,6 +714,9 @@ impl State {
atspi_state, atspi_state,
atspi_ei: Default::default(), atspi_ei: Default::default(),
#[cfg(feature = "systemd")]
inhibit_lid_fd: None,
}, },
backend: BackendData::Unset, backend: BackendData::Unset,
ready: Once::new(), ready: Once::new(),
@ -726,6 +736,34 @@ impl State {
security_context: None, 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>( fn primary_scanout_output_compare<'a>(