From ce3efbf9ac9f5e487b7ac309bf45b2ac900e181c Mon Sep 17 00:00:00 2001 From: Federico Maria Morrone Date: Thu, 21 Nov 2024 18:03:38 +0100 Subject: [PATCH] Add support for cosmic atspi protocol --- gen/src/protocols.json | 1 + src/client/protocol/cosmic.rs | 104 ++++++++++++++++++++++++++++++ src/server/protocol/cosmic.rs | 116 ++++++++++++++++++++++++++++++++++ 3 files changed, 221 insertions(+) diff --git a/gen/src/protocols.json b/gen/src/protocols.json index 70b50e2..d42a6cb 100644 --- a/gen/src/protocols.json +++ b/gen/src/protocols.json @@ -119,6 +119,7 @@ ], "cosmic": [ + "protocols/cosmic-protocols/unstable/cosmic-atspi-unstable-v1.xml", "protocols/cosmic-protocols/unstable/cosmic-image-source-unstable-v1.xml", "protocols/cosmic-protocols/unstable/cosmic-output-management-unstable-v1.xml", "protocols/cosmic-protocols/unstable/cosmic-overlap-notify-unstable-v1.xml", diff --git a/src/client/protocol/cosmic.rs b/src/client/protocol/cosmic.rs index d25e8b7..7cf63c3 100644 --- a/src/client/protocol/cosmic.rs +++ b/src/client/protocol/cosmic.rs @@ -1,4 +1,108 @@ #![allow(async_fn_in_trait)] +#[doc = "This protocol provides a relatively straightforward mapping of AtpsiDevice"] +#[doc = "in the at-spi2-core library, so it's possible to add a Wayland backend for it."] +#[doc = ""] +#[doc = "This provides a way for screen reader key bindings to work."] +#[doc = ""] +#[doc = "This is a temporary solution until a better protocol is available for this purpose."] +pub mod cosmic_atspi_v1 { + #[doc = "Manager for adding grabs and monitoring key input."] + pub mod cosmic_atspi_manager_v1 { + use futures_util::SinkExt; + #[doc = "Trait to implement the cosmic_atspi_manager_v1 interface. See the module level documentation for more info"] + pub trait CosmicAtspiManagerV1 { + const INTERFACE: &'static str = "cosmic_atspi_manager_v1"; + const VERSION: u32 = 1u32; + async fn handle_event( + &self, + message: &mut crate::wire::Message, + ) -> crate::client::Result<()> { + match message.opcode { + _ => Err(crate::client::Error::UnknownOpcode), + } + } + #[doc = "Any grabs that are still active will be disabled."] + async fn destroy( + &self, + socket: &mut crate::wire::Socket, + object_id: crate::wire::ObjectId, + ) -> crate::client::Result<()> { + tracing::debug!("-> cosmic_atspi_manager_v1#{}.destroy()", object_id); + let (payload, fds) = crate::wire::PayloadBuilder::new().build(); + socket + .send(crate::wire::Message::new(object_id, 0u16, payload, fds)) + .await + .map_err(crate::client::Error::IoError) + } + #[doc = "Grab the given key combination, so it will not be sent to clients."] + async fn add_key_grab( + &self, + socket: &mut crate::wire::Socket, + object_id: crate::wire::ObjectId, + mods: u32, + virtual_mods: Vec, + key: u32, + ) -> crate::client::Result<()> { + tracing::debug!("-> cosmic_atspi_manager_v1#{}.add_key_grab()", object_id); + let (payload, fds) = crate::wire::PayloadBuilder::new() + .put_uint(mods) + .put_array(virtual_mods) + .put_uint(key) + .build(); + socket + .send(crate::wire::Message::new(object_id, 1u16, payload, fds)) + .await + .map_err(crate::client::Error::IoError) + } + #[doc = "Disables a grab added with add_key_grab."] + async fn remove_key_grab( + &self, + socket: &mut crate::wire::Socket, + object_id: crate::wire::ObjectId, + mods: u32, + virtual_mods: Vec, + key: u32, + ) -> crate::client::Result<()> { + tracing::debug!("-> cosmic_atspi_manager_v1#{}.remove_key_grab()", object_id); + let (payload, fds) = crate::wire::PayloadBuilder::new() + .put_uint(mods) + .put_array(virtual_mods) + .put_uint(key) + .build(); + socket + .send(crate::wire::Message::new(object_id, 2u16, payload, fds)) + .await + .map_err(crate::client::Error::IoError) + } + #[doc = "Grab keyboard, so key input will not be sent to clients."] + async fn grab_keyboard( + &self, + socket: &mut crate::wire::Socket, + object_id: crate::wire::ObjectId, + ) -> crate::client::Result<()> { + tracing::debug!("-> cosmic_atspi_manager_v1#{}.grab_keyboard()", object_id); + let (payload, fds) = crate::wire::PayloadBuilder::new().build(); + socket + .send(crate::wire::Message::new(object_id, 3u16, payload, fds)) + .await + .map_err(crate::client::Error::IoError) + } + #[doc = "Disables a grab added with grab_keyboard."] + async fn ungrab_keyboard( + &self, + socket: &mut crate::wire::Socket, + object_id: crate::wire::ObjectId, + ) -> crate::client::Result<()> { + tracing::debug!("-> cosmic_atspi_manager_v1#{}.ungrab_keyboard()", object_id); + let (payload, fds) = crate::wire::PayloadBuilder::new().build(); + socket + .send(crate::wire::Message::new(object_id, 4u16, payload, fds)) + .await + .map_err(crate::client::Error::IoError) + } + } + } +} #[doc = "This protocol serves as an intermediary between screen capturing protocols"] #[doc = "and potential image sources such as outputs and toplevels."] #[doc = ""] diff --git a/src/server/protocol/cosmic.rs b/src/server/protocol/cosmic.rs index 9fe408c..17dee18 100644 --- a/src/server/protocol/cosmic.rs +++ b/src/server/protocol/cosmic.rs @@ -1,4 +1,120 @@ #![allow(async_fn_in_trait)] +#[doc = "This protocol provides a relatively straightforward mapping of AtpsiDevice"] +#[doc = "in the at-spi2-core library, so it's possible to add a Wayland backend for it."] +#[doc = ""] +#[doc = "This provides a way for screen reader key bindings to work."] +#[doc = ""] +#[doc = "This is a temporary solution until a better protocol is available for this purpose."] +pub mod cosmic_atspi_v1 { + #[doc = "Manager for adding grabs and monitoring key input."] + pub mod cosmic_atspi_manager_v1 { + #[doc = "Trait to implement the cosmic_atspi_manager_v1 interface. See the module level documentation for more info"] + pub trait CosmicAtspiManagerV1: crate::server::Dispatcher { + const INTERFACE: &'static str = "cosmic_atspi_manager_v1"; + const VERSION: u32 = 1u32; + fn into_object(self, id: crate::wire::ObjectId) -> crate::server::Object + where + Self: Sized, + { + crate::server::Object::new(id, self) + } + async fn handle_request( + &self, + object: &crate::server::Object, + client: &mut crate::server::Client, + message: &mut crate::wire::Message, + ) -> crate::server::Result<()> { + match message.opcode { + 0u16 => { + tracing::debug!("cosmic_atspi_manager_v1#{}.destroy()", object.id); + self.destroy(object, client).await + } + 1u16 => { + tracing::debug!("cosmic_atspi_manager_v1#{}.add_key_grab()", object.id); + self.add_key_grab( + object, + client, + message.uint()?, + message.array()?, + message.uint()?, + ) + .await + } + 2u16 => { + tracing::debug!("cosmic_atspi_manager_v1#{}.remove_key_grab()", object.id); + self.remove_key_grab( + object, + client, + message.uint()?, + message.array()?, + message.uint()?, + ) + .await + } + 3u16 => { + tracing::debug!("cosmic_atspi_manager_v1#{}.grab_keyboard()", object.id); + self.grab_keyboard(object, client).await + } + 4u16 => { + tracing::debug!("cosmic_atspi_manager_v1#{}.ungrab_keyboard()", object.id); + self.ungrab_keyboard(object, client).await + } + _ => Err(crate::server::error::Error::UnknownOpcode), + } + } + #[doc = "Any grabs that are still active will be disabled."] + async fn destroy( + &self, + object: &crate::server::Object, + client: &mut crate::server::Client, + ) -> crate::server::Result<()>; + #[doc = "Grab the given key combination, so it will not be sent to clients."] + async fn add_key_grab( + &self, + object: &crate::server::Object, + client: &mut crate::server::Client, + mods: u32, + virtual_mods: Vec, + key: u32, + ) -> crate::server::Result<()>; + #[doc = "Disables a grab added with add_key_grab."] + async fn remove_key_grab( + &self, + object: &crate::server::Object, + client: &mut crate::server::Client, + mods: u32, + virtual_mods: Vec, + key: u32, + ) -> crate::server::Result<()>; + #[doc = "Grab keyboard, so key input will not be sent to clients."] + async fn grab_keyboard( + &self, + object: &crate::server::Object, + client: &mut crate::server::Client, + ) -> crate::server::Result<()>; + #[doc = "Disables a grab added with grab_keyboard."] + async fn ungrab_keyboard( + &self, + object: &crate::server::Object, + client: &mut crate::server::Client, + ) -> crate::server::Result<()>; + #[doc = "Produces an fd that can be used with libei to monitor keyboard input."] + async fn key_events_eis( + &self, + object: &crate::server::Object, + client: &mut crate::server::Client, + fd: rustix::fd::OwnedFd, + ) -> crate::server::Result<()> { + tracing::debug!("-> cosmic_atspi_manager_v1#{}.key_events_eis()", object.id); + let (payload, fds) = crate::wire::PayloadBuilder::new().put_fd(fd).build(); + client + .send_message(crate::wire::Message::new(object.id, 0u16, payload, fds)) + .await + .map_err(crate::server::error::Error::IoError) + } + } + } +} #[doc = "This protocol serves as an intermediary between screen capturing protocols"] #[doc = "and potential image sources such as outputs and toplevels."] #[doc = ""]