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

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 zbus::blocking::{fdo::DBusProxy, Connection};
#[cfg(feature = "systemd")]
pub mod logind;
mod power;
pub fn init(evlh: &LoopHandle<'static, State>) -> Result<Vec<RegistrationToken>> {

View file

@ -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<OwnedFd>,
}
#[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>(