diff options
| author | Ivan Molodetskikh <yalterz@gmail.com> | 2024-06-26 10:08:07 +0400 |
|---|---|---|
| committer | Ivan Molodetskikh <yalterz@gmail.com> | 2024-06-28 10:39:35 +0400 |
| commit | 40aff3a094756b2cfa9c0ce48c1ab2be26b1f9ee (patch) | |
| tree | 662ddc0e7ecb92bc01e025d7f7c54a0522e91d9e /src/dbus | |
| parent | 6c5f10035a24963336d99f801164e7437ebffa77 (diff) | |
| download | niri-40aff3a094756b2cfa9c0ce48c1ab2be26b1f9ee.tar.gz niri-40aff3a094756b2cfa9c0ce48c1ab2be26b1f9ee.tar.bz2 niri-40aff3a094756b2cfa9c0ce48c1ab2be26b1f9ee.zip | |
Implement org/gnome/shell/Introspect/GetWindows
Diffstat (limited to 'src/dbus')
| -rw-r--r-- | src/dbus/gnome_shell_introspect.rs | 81 | ||||
| -rw-r--r-- | src/dbus/mod.rs | 16 |
2 files changed, 97 insertions, 0 deletions
diff --git a/src/dbus/gnome_shell_introspect.rs b/src/dbus/gnome_shell_introspect.rs new file mode 100644 index 00000000..d9485d81 --- /dev/null +++ b/src/dbus/gnome_shell_introspect.rs @@ -0,0 +1,81 @@ +use std::collections::HashMap; + +use zbus::fdo::{self, RequestNameFlags}; +use zbus::zvariant::{SerializeDict, Type, Value}; +use zbus::{dbus_interface, SignalContext}; + +use super::Start; + +pub struct Introspect { + to_niri: calloop::channel::Sender<IntrospectToNiri>, + from_niri: async_channel::Receiver<NiriToIntrospect>, +} + +pub enum IntrospectToNiri { + GetWindows, +} + +pub enum NiriToIntrospect { + Windows(HashMap<u64, WindowProperties>), +} + +#[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, +} + +#[dbus_interface(name = "org.gnome.Shell.Introspect")] +impl Introspect { + async fn get_windows(&self) -> fdo::Result<HashMap<u64, WindowProperties>> { + 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). + #[dbus_interface(signal)] + pub async fn windows_changed(ctxt: &SignalContext<'_>) -> zbus::Result<()>; +} + +impl Introspect { + pub fn new( + to_niri: calloop::channel::Sender<IntrospectToNiri>, + from_niri: async_channel::Receiver<NiriToIntrospect>, + ) -> Self { + Self { to_niri, from_niri } + } +} + +impl Start for Introspect { + fn start(self) -> anyhow::Result<zbus::blocking::Connection> { + 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) + } +} diff --git a/src/dbus/mod.rs b/src/dbus/mod.rs index 7d63682d..179f10a7 100644 --- a/src/dbus/mod.rs +++ b/src/dbus/mod.rs @@ -4,6 +4,7 @@ use zbus::Interface; use crate::niri::State; pub mod freedesktop_screensaver; +pub mod gnome_shell_introspect; pub mod gnome_shell_screenshot; pub mod mutter_display_config; pub mod mutter_service_channel; @@ -14,6 +15,7 @@ pub mod mutter_screen_cast; use mutter_screen_cast::ScreenCast; use self::freedesktop_screensaver::ScreenSaver; +use self::gnome_shell_introspect::Introspect; use self::mutter_display_config::DisplayConfig; use self::mutter_service_channel::ServiceChannel; @@ -27,6 +29,7 @@ pub struct DBusServers { pub conn_display_config: Option<Connection>, pub conn_screen_saver: Option<Connection>, pub conn_screen_shot: Option<Connection>, + pub conn_introspect: Option<Connection>, #[cfg(feature = "xdp-gnome-screencast")] pub conn_screen_cast: Option<Connection>, } @@ -66,6 +69,19 @@ impl DBusServers { let screenshot = gnome_shell_screenshot::Screenshot::new(to_niri, from_niri); dbus.conn_screen_shot = try_start(screenshot); + let (to_niri, from_introspect) = calloop::channel::channel(); + let (to_introspect, from_niri) = async_channel::unbounded(); + niri.event_loop + .insert_source(from_introspect, move |event, _, state| match event { + calloop::channel::Event::Msg(msg) => { + state.on_introspect_msg(&to_introspect, msg) + } + calloop::channel::Event::Closed => (), + }) + .unwrap(); + let introspect = Introspect::new(to_niri, from_niri); + dbus.conn_introspect = try_start(introspect); + #[cfg(feature = "xdp-gnome-screencast")] if niri.pipewire.is_some() { let (to_niri, from_screen_cast) = calloop::channel::channel(); |
