use std::collections::HashMap; use zbus::fdo::{self, RequestNameFlags}; use zbus::interface; use zbus::object_server::SignalEmitter; use zbus::zvariant::{SerializeDict, Type, Value}; use super::Start; pub struct Introspect { to_niri: calloop::channel::Sender, from_niri: async_channel::Receiver, } pub enum IntrospectToNiri { GetWindows, } pub enum NiriToIntrospect { Windows(HashMap), } #[derive(Debug, SerializeDict, Type, Value)] #[zvariant(signature = "dict")] pub struct WindowProperties { /// Window title. pub title: String, /// Window app ID. /// /// This is actually the name of the .desktop file, and Shell does internal tracking to match /// Wayland app IDs to desktop files. We don't do that yet, which is the reason why /// xdg-desktop-portal-gnome's window list is missing icons. #[zvariant(rename = "app-id")] pub app_id: String, } #[interface(name = "org.gnome.Shell.Introspect")] impl Introspect { async fn get_windows(&self) -> fdo::Result> { if let Err(err) = self.to_niri.send(IntrospectToNiri::GetWindows) { warn!("error sending message to niri: {err:?}"); return Err(fdo::Error::Failed("internal error".to_owned())); } match self.from_niri.recv().await { Ok(NiriToIntrospect::Windows(windows)) => Ok(windows), Err(err) => { warn!("error receiving message from niri: {err:?}"); Err(fdo::Error::Failed("internal error".to_owned())) } } } // FIXME: call this upon window changes, once more of the infrastructure is there (will be // needed for the event stream IPC anyway). #[zbus(signal)] pub async fn windows_changed(ctxt: &SignalEmitter<'_>) -> zbus::Result<()>; } impl Introspect { pub fn new( to_niri: calloop::channel::Sender, from_niri: async_channel::Receiver, ) -> Self { Self { to_niri, from_niri } } } impl Start for Introspect { fn start(self) -> anyhow::Result { let conn = zbus::blocking::Connection::session()?; let flags = RequestNameFlags::AllowReplacement | RequestNameFlags::ReplaceExisting | RequestNameFlags::DoNotQueue; conn.object_server() .at("/org/gnome/Shell/Introspect", self)?; conn.request_name_with_flags("org.gnome.Shell.Introspect", flags)?; Ok(conn) } }