dbus: Refactor to share DBus connections

We should avoid creating more than one session connection or more than
one system connection. We should also ideally avoid blocking the main
thread.

For now this still uses blocking in a couple places, but wrapping async
code (which is how `zbus::blocking` is implemented anyway).

This moves the `NameOwners` creation out of `A11yKeyboardMonitorState`,
so it can be shared with other things. We will likely want that for
https://github.com/pop-os/cosmic-comp/pull/465 to define a secured
protocol to pass an fd to the portal, and potentially any other
sensitive DBus protocols implemented by the compositor.
This commit is contained in:
Ian Douglas Scott 2026-03-05 15:56:06 -08:00 • committed by Victoria Brekenfeld
parent c8d9ff1215
commit 4eaaf4f55c
9 changed files with 238 additions and 173 deletions

View file

@ -8,7 +8,7 @@ use crate::{
x11::X11State,
},
config::{CompOutputConfig, Config, ScreenFilter},
dbus::a11y_keyboard_monitor::A11yKeyboardMonitorState,
dbus::DBusState,
input::{PointerFocusState, gestures::GestureState},
shell::{CosmicSurface, SeatExt, Shell, grabs::SeatMoveGrabState},
utils::prelude::OutputExt,
@ -233,7 +233,6 @@ pub struct Common {
pub display_handle: DisplayHandle,
pub event_loop_handle: LoopHandle<'static, State>,
pub event_loop_signal: LoopSignal,
pub async_executor: calloop::futures::Scheduler<()>,
pub popups: PopupManager,
pub shell: Arc<parking_lot::RwLock<Shell>>,
@ -278,7 +277,7 @@ pub struct Common {
pub xdg_decoration_state: XdgDecorationState,
pub overlap_notify_state: OverlapNotifyState,
pub a11y_state: A11yState,
pub a11y_keyboard_monitor_state: A11yKeyboardMonitorState,
pub dbus_state: DBusState,
// shell-related wayland state
pub xdg_shell_state: XdgShellState,
@ -726,16 +725,9 @@ impl State {
);
let workspace_state = WorkspaceState::new(dh, client_not_sandboxed);
let (source, async_executor) = calloop::futures::executor().unwrap();
handle.insert_source(source, |_, _, _| {}).unwrap();
if let Err(err) = crate::dbus::init(&handle) {
tracing::warn!(?err, "Failed to initialize dbus handlers");
}
let a11y_state = A11yState::new::<State, _>(dh, client_not_sandboxed);
let a11y_keyboard_monitor_state = A11yKeyboardMonitorState::new(&async_executor);
let dbus_state = DBusState::init(&handle);
State {
common: Common {
@ -744,7 +736,6 @@ impl State {
display_handle: dh.clone(),
event_loop_handle: handle,
event_loop_signal: signal,
async_executor,
popups: PopupManager::default(),
shell,
@ -794,11 +785,11 @@ impl State {
xdg_foreign_state,
workspace_state,
a11y_state,
a11y_keyboard_monitor_state,
xwayland_scale: None,
xwayland_state: None,
xwayland_shell_state,
pointer_focus_state: None,
dbus_state,
#[cfg(feature = "systemd")]
inhibit_lid_fd: None,
@ -841,7 +832,7 @@ impl State {
if should_handle_lid {
if self.common.inhibit_lid_fd.is_none() {
match crate::dbus::logind::inhibit_lid() {
match crate::dbus::logind::inhibit_lid(&self.common) {
Ok(fd) => {
debug!("Inhibiting lid switch");
self.common.inhibit_lid_fd = Some(fd);
@ -852,7 +843,8 @@ impl State {
.iter()
.find(|o| o.is_internal())
.cloned();
let closed = crate::dbus::logind::lid_closed().unwrap_or(false);
let closed =
crate::dbus::logind::lid_closed(&self.common).unwrap_or(false);
if closed {
backend.disable_internal_output(