use smithay::reexports::calloop; use zbus::blocking::Connection; use zbus::Interface; use crate::niri::State; pub mod gnome_shell_screenshot; pub mod mutter_display_config; pub mod mutter_service_channel; #[cfg(feature = "xdp-gnome-screencast")] pub mod mutter_screen_cast; #[cfg(feature = "xdp-gnome-screencast")] use mutter_screen_cast::ScreenCast; use self::mutter_display_config::DisplayConfig; use self::mutter_service_channel::ServiceChannel; trait Start: Interface { fn start(self) -> anyhow::Result; } #[derive(Default)] pub struct DBusServers { pub conn_service_channel: Option, pub conn_display_config: Option, pub conn_screen_shot: Option, #[cfg(feature = "xdp-gnome-screencast")] pub conn_screen_cast: Option, } impl DBusServers { pub fn start(state: &mut State, is_session_instance: bool) { let _span = tracy_client::span!("DBusServers::start"); let backend = &state.backend; let niri = &mut state.niri; let config = niri.config.borrow(); let mut dbus = Self::default(); if is_session_instance { let service_channel = ServiceChannel::new(niri.display_handle.clone()); dbus.conn_service_channel = try_start(service_channel); } if is_session_instance || config.debug.dbus_interfaces_in_non_session_instances { let display_config = DisplayConfig::new(backend.connectors()); dbus.conn_display_config = try_start(display_config); let (to_niri, from_screenshot) = calloop::channel::channel(); let (to_screenshot, from_niri) = async_channel::unbounded(); niri.event_loop .insert_source(from_screenshot, move |event, _, state| match event { calloop::channel::Event::Msg(msg) => { state.on_screen_shot_msg(&to_screenshot, msg) } calloop::channel::Event::Closed => (), }) .unwrap(); let screenshot = gnome_shell_screenshot::Screenshot::new(to_niri, from_niri); dbus.conn_screen_shot = try_start(screenshot); #[cfg(feature = "xdp-gnome-screencast")] { let (to_niri, from_screen_cast) = calloop::channel::channel(); niri.event_loop .insert_source(from_screen_cast, { let to_niri = to_niri.clone(); move |event, _, state| match event { calloop::channel::Event::Msg(msg) => { state.on_screen_cast_msg(&to_niri, msg) } calloop::channel::Event::Closed => (), } }) .unwrap(); let screen_cast = ScreenCast::new(backend.connectors(), to_niri); dbus.conn_screen_cast = try_start(screen_cast); } } niri.dbus = Some(dbus); } } fn try_start(iface: I) -> Option { match iface.start() { Ok(conn) => Some(conn), Err(err) => { warn!("error starting {}: {err:?}", I::name()); None } } }