atspi_common/events/
registry.rs

1//! This module contains the events that are emitted by the registry daemon.
2//! The events are [`EventListenerRegisteredEvent`] and [`EventListenerDeregisteredEvent`].
3
4#[cfg(feature = "zbus")]
5use crate::object_ref::ObjectRef;
6#[cfg(feature = "zbus")]
7use crate::{error::AtspiError, events::MessageConversion, EventProperties};
8use serde::{Deserialize, Serialize};
9#[cfg(feature = "zbus")]
10use zbus::message::{Body as DbusBody, Header};
11use zbus_lockstep_macros::validate;
12use zbus_names::{OwnedUniqueName, UniqueName};
13use zvariant::Type;
14
15use crate::{
16	events::{DBusInterface, DBusMatchRule, DBusMember, RegistryEventString},
17	object_ref::ObjectRefOwned,
18};
19
20/// An event that is emitted by the registry daemon, to inform that an event has been deregistered
21/// to no longer listen for.
22#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default, Eq, Hash)]
23pub struct EventListenerDeregisteredEvent {
24	/// The [`ObjectRef`] the event applies to.
25	pub item: ObjectRefOwned,
26	/// A list of events that have been deregistered via the registry interface.
27	/// See `atspi-connection`.
28	pub deregistered_event: EventListeners,
29}
30
31impl_event_type_properties_for_event!(EventListenerDeregisteredEvent);
32
33event_test_cases!(EventListenerDeregisteredEvent, Explicit);
34
35// The registry string cannot be found in upstrream at-spi2-core.
36
37impl_member_interface_registry_string_and_match_rule_for_event!(
38	EventListenerDeregisteredEvent,
39	"EventListenerDeregistered",
40	"org.a11y.atspi.Registry",
41	"registry:event-listener-deregistered",
42	"type='signal',interface='org.a11y.atspi.Registry',member='EventListenerDeregistered'"
43);
44
45#[cfg(feature = "zbus")]
46impl MessageConversion<'_> for EventListenerDeregisteredEvent {
47	type Body<'a> = EventListeners;
48
49	fn from_message_unchecked_parts(item: ObjectRef, body: DbusBody) -> Result<Self, AtspiError> {
50		let deregistered_event = body.deserialize_unchecked::<Self::Body<'_>>()?;
51		Ok(Self { item: item.into(), deregistered_event })
52	}
53
54	fn from_message_unchecked(msg: &zbus::Message, header: &Header) -> Result<Self, AtspiError> {
55		let item = header.try_into()?;
56		let body = msg.body();
57		Self::from_message_unchecked_parts(item, body)
58	}
59
60	fn body(&self) -> Self::Body<'_> {
61		self.deregistered_event.clone()
62	}
63}
64
65impl_msg_conversion_ext_for_target_type_with_specified_body_type!(target: EventListenerDeregisteredEvent, body: EventListeners);
66impl_from_dbus_message!(EventListenerDeregisteredEvent, Explicit);
67impl_event_properties!(EventListenerDeregisteredEvent);
68impl_to_dbus_message!(EventListenerDeregisteredEvent);
69
70/// An event that is emitted by the regostry daemon to signal that an event has been registered to listen for.
71#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default, Eq, Hash)]
72pub struct EventListenerRegisteredEvent {
73	/// The [`ObjectRef`] the event applies to.
74	pub item: ObjectRefOwned,
75	/// A list of events that have been registered via the registry interface.
76	/// See `atspi-connection`.
77	pub registered_event: EventListeners,
78}
79
80impl_event_type_properties_for_event!(EventListenerRegisteredEvent);
81
82#[cfg(feature = "zbus")]
83impl MessageConversion<'_> for EventListenerRegisteredEvent {
84	type Body<'a> = EventListeners;
85
86	fn from_message_unchecked_parts(
87		item: ObjectRef,
88		registered_event: DbusBody,
89	) -> Result<Self, AtspiError> {
90		let registered_event = registered_event.deserialize_unchecked()?;
91		Ok(Self { item: item.into(), registered_event })
92	}
93
94	fn from_message_unchecked(msg: &zbus::Message, header: &Header) -> Result<Self, AtspiError> {
95		let item = header.try_into()?;
96		let body = msg.body();
97		Self::from_message_unchecked_parts(item, body)
98	}
99
100	fn body(&self) -> Self::Body<'_> {
101		self.registered_event.clone()
102	}
103}
104
105impl_msg_conversion_ext_for_target_type_with_specified_body_type!(target: EventListenerRegisteredEvent, body: EventListeners);
106impl_from_dbus_message!(EventListenerRegisteredEvent, Explicit);
107impl_event_properties!(EventListenerRegisteredEvent);
108impl_to_dbus_message!(EventListenerRegisteredEvent);
109
110event_test_cases!(EventListenerRegisteredEvent, Explicit);
111
112// The registry string cannot be found in upstrream at-spi2-core.
113impl_member_interface_registry_string_and_match_rule_for_event!(
114	EventListenerRegisteredEvent,
115	"EventListenerRegistered",
116	"org.a11y.atspi.Registry",
117	"registry:event-listener-registered",
118	"type='signal',interface='org.a11y.atspi.Registry',member='EventListenerRegistered'"
119);
120
121/// Signal type emitted by `EventListenerRegistered` and `EventListenerDeregistered` signals,
122/// which belong to the `Registry` interface, implemented by the registry-daemon.
123#[validate(signal: "EventListenerRegistered")]
124#[derive(Debug, Clone, Serialize, Deserialize, Type, PartialEq, Eq, Hash)]
125pub struct EventListeners {
126	pub bus_name: OwnedUniqueName,
127	// TODO: `path` should be a `zvariant::ObjectPath` but that requires changing the signature with an attribute
128	// and `Serialize`/`Deserialize` impls.
129	pub path: String,
130}
131
132impl Default for EventListeners {
133	fn default() -> Self {
134		Self {
135			bus_name: UniqueName::from_static_str_unchecked(":0.0").into(),
136			path: String::from("/org/a11y/atspi/null"),
137		}
138	}
139}
140
141#[cfg(test)]
142mod event_listener_tests {
143	use super::*;
144
145	#[test]
146	fn test_event_listener_default_no_panic() {
147		let el = EventListeners::default();
148		assert_eq!(el.bus_name.as_str(), ":0.0");
149		assert_eq!(el.path.as_str(), "/org/a11y/atspi/null");
150	}
151}
152
153pub mod socket {
154	//! This module contains the event that is emitted by the registry daemon's `Socket` interface.
155
156	#[cfg(feature = "zbus")]
157	use crate::events::MessageConversion;
158	use crate::events::{DBusInterface, DBusMatchRule, DBusMember, RegistryEventString};
159	use crate::object_ref::ObjectRefOwned;
160	#[cfg(feature = "zbus")]
161	use crate::AtspiError;
162	#[cfg(feature = "zbus")]
163	use crate::EventProperties;
164	#[cfg(feature = "zbus")]
165	use crate::ObjectRef;
166	#[cfg(feature = "zbus")]
167	use zbus::message::{Body as DbusBody, Header};
168
169	use serde::{Deserialize, Serialize};
170
171	/// An event that is emitted when the registry daemon has started.
172	///
173	/// The accessibility registry emits this signal early during startup,
174	/// when it has registered with the `DBus` daemon and is available for
175	/// calls from applications.
176	#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Default, Eq, Hash)]
177	pub struct AvailableEvent {
178		/// The emitting [`ObjectRef`].
179		pub item: ObjectRefOwned,
180
181		/// The [`ObjectRef`] for the Registry's root object.
182		pub socket: ObjectRefOwned,
183	}
184
185	impl_event_type_properties_for_event!(AvailableEvent);
186
187	event_test_cases!(AvailableEvent, Explicit);
188
189	// We cannot register at Registry for this event, as it is emitted by the Registry itself at early startup.
190	// So, we do not have a registry event string for this event.
191	// The `Available` event is unconditionally emitted:
192	// [at-spi2-core/registryd/registry.c:1437](https://github.com/GNOME/at-spi2-core/blob/019d1a4013216d7d01040cf4eb3b8647bffc0dc9/registryd/registry.c#L1437)
193	impl_member_interface_registry_string_and_match_rule_for_event!(
194		AvailableEvent,
195		"Available",
196		"org.a11y.atspi.Socket",
197		"",
198		"type='signal',interface='org.a11y.atspi.Socket',member='Available'"
199	);
200
201	#[cfg(feature = "zbus")]
202	impl MessageConversion<'_> for AvailableEvent {
203		type Body<'a> = ObjectRef<'a>;
204
205		fn from_message_unchecked_parts(
206			item: ObjectRef<'_>,
207			body: DbusBody,
208		) -> Result<Self, AtspiError> {
209			let socket = body.deserialize_unchecked::<Self::Body<'_>>()?;
210			Ok(Self { item: item.into(), socket: socket.into() })
211		}
212
213		fn from_message_unchecked(
214			msg: &zbus::Message,
215			header: &Header,
216		) -> Result<Self, AtspiError> {
217			let item = header.try_into()?;
218			let body = msg.body();
219			Self::from_message_unchecked_parts(item, body)
220		}
221
222		fn body(&self) -> Self::Body<'_> {
223			self.socket.clone().into_inner()
224		}
225	}
226
227	impl_msg_conversion_ext_for_target_type_with_specified_body_type!(target: AvailableEvent, body: ObjectRef<'a>);
228	impl_from_dbus_message!(AvailableEvent, Explicit);
229	impl_event_properties!(AvailableEvent);
230	impl_to_dbus_message!(AvailableEvent);
231}