aboutsummaryrefslogtreecommitdiff
path: root/src/dbus
diff options
context:
space:
mode:
authorIvan Molodetskikh <yalterz@gmail.com>2024-06-26 10:08:07 +0400
committerIvan Molodetskikh <yalterz@gmail.com>2024-06-28 10:39:35 +0400
commit40aff3a094756b2cfa9c0ce48c1ab2be26b1f9ee (patch)
tree662ddc0e7ecb92bc01e025d7f7c54a0522e91d9e /src/dbus
parent6c5f10035a24963336d99f801164e7437ebffa77 (diff)
downloadniri-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.rs81
-rw-r--r--src/dbus/mod.rs16
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();