1pub mod cache;
2pub mod document;
3#[cfg(feature = "wrappers")]
4pub mod event_wrappers;
5
6pub use event_body::{EventBodyBorrowed, EventBodyOwned, EventBodyQtBorrowed, EventBodyQtOwned};
7#[cfg(feature = "wrappers")]
8pub use event_wrappers::{
9 CacheEvents, DocumentEvents, Event, FocusEvents, KeyboardEvents, MouseEvents, ObjectEvents,
10 TerminalEvents, WindowEvents,
11};
12pub mod event_body;
13pub mod focus;
14pub mod keyboard;
15pub mod mouse;
16pub mod object;
17pub mod terminal;
18pub mod traits;
19pub mod window;
20pub use traits::*;
21
22pub(crate) const QSPI_EVENT_SIGNATURE: &Signature = &Signature::static_structure(&[
25 &Signature::Str,
26 &Signature::I32,
27 &Signature::I32,
28 &Signature::Variant,
29 &Signature::Structure(Fields::Static { fields: &[&Signature::Str, &Signature::ObjectPath] }),
30]);
31
32use serde::{Deserialize, Serialize};
33use zbus_lockstep_macros::validate;
34use zbus_names::{OwnedUniqueName, UniqueName};
35#[cfg(feature = "zbus")]
36use zvariant::OwnedObjectPath;
37use zvariant::{signature::Fields, ObjectPath, Signature, Type};
38
39#[cfg(feature = "zbus")]
40use crate::AtspiError;
41use crate::ObjectRef;
42
43impl HasInterfaceName for EventListenerEvents {
44 const DBUS_INTERFACE: &'static str = "org.a11y.atspi.Registry";
45}
46
47impl HasMatchRule for EventListenerEvents {
48 const MATCH_RULE_STRING: &'static str =
49 "type='signal',interface='org.a11y.atspi.Event.Registry'";
50}
51
52impl HasRegistryEventString for EventListenerEvents {
53 const REGISTRY_EVENT_STRING: &'static str = "Event";
54}
55
56#[cfg(feature = "zbus")]
57impl<T> MessageConversion for T
58where
59 ObjectRef: Into<T>,
60 T: BusProperties,
63{
64 type Body = EventBodyOwned;
65 fn from_message_unchecked_parts(obj_ref: ObjectRef, _: Self::Body) -> Result<Self, AtspiError> {
66 Ok(obj_ref.into())
67 }
68 fn from_message_unchecked(msg: &zbus::Message) -> Result<Self, AtspiError> {
69 let item: ObjectRef = msg.try_into()?;
70 Ok(item.into())
71 }
72 fn body(&self) -> Self::Body {
73 EventBodyOwned::default()
74 }
75}
76
77impl<T: BusProperties> HasMatchRule for T {
78 const MATCH_RULE_STRING: &'static str = <T as BusProperties>::MATCH_RULE_STRING;
79}
80impl<T: BusProperties> HasRegistryEventString for T {
81 const REGISTRY_EVENT_STRING: &'static str = <T as BusProperties>::REGISTRY_EVENT_STRING;
82}
83impl<T: BusProperties> HasInterfaceName for T {
84 const DBUS_INTERFACE: &'static str = <T as BusProperties>::DBUS_INTERFACE;
85}
86
87#[cfg(test)]
88mod accessible_deserialization_tests {
89 use crate::events::ObjectRef;
90 use zvariant::Value;
91
92 #[test]
93 fn try_into_value() {
94 let acc = ObjectRef::default();
95 let value_struct = Value::from(acc);
96 let Value::Structure(structure) = value_struct else {
97 panic!("Unable to destructure a structure out of the Value.");
98 };
99 let vals = structure.into_fields();
100 assert_eq!(vals.len(), 2);
101 let Value::Str(bus_name) = vals.first().unwrap() else {
102 panic!("Unable to destructure field value: {:?}", vals.first().unwrap());
103 };
104 assert_eq!(bus_name, ":0.0");
105 let Value::ObjectPath(path) = vals.last().unwrap() else {
106 panic!("Unable to destructure field value: {:?}", vals.get(1).unwrap());
107 };
108 assert_eq!(path.as_str(), "/org/a11y/atspi/accessible/null");
109 }
110 #[test]
111 fn try_from_value() {}
112}
113
114#[cfg(test)]
115mod accessible_tests {
116 use super::ObjectRef;
117
118 #[test]
119 fn test_accessible_default_doesnt_panic() {
120 let acc = ObjectRef::default();
121 assert_eq!(acc.name.as_str(), ":0.0");
122 assert_eq!(acc.path.as_str(), "/org/a11y/atspi/accessible/null");
123 }
124}
125#[cfg(feature = "zbus")]
126impl TryFrom<&zbus::Message> for ObjectRef {
127 type Error = AtspiError;
128 fn try_from(message: &zbus::Message) -> Result<Self, Self::Error> {
129 let header = message.header();
130 let path = header.path().expect("returned path is either `Some` or panics");
131 let owned_path: OwnedObjectPath = path.clone().into();
132
133 let sender: UniqueName<'_> = header.sender().expect("No sender in header").into();
134 let name: OwnedUniqueName = sender.to_owned().into();
135
136 Ok(ObjectRef { name, path: owned_path })
137 }
138}
139
140#[validate(signal: "EventListenerRegistered")]
143#[derive(Debug, Clone, Serialize, Deserialize, Type, PartialEq, Eq, Hash)]
144pub struct EventListeners {
145 pub bus_name: OwnedUniqueName,
146 pub path: String,
147}
148
149impl Default for EventListeners {
150 fn default() -> Self {
151 Self {
152 bus_name: UniqueName::try_from(":0.0").unwrap().into(),
153 path: "/org/a11y/atspi/accessible/null".to_string(),
154 }
155 }
156}
157
158#[cfg(test)]
159#[test]
160fn test_event_listener_default_no_panic() {
161 let el = EventListeners::default();
162 assert_eq!(el.bus_name.as_str(), ":0.0");
163 assert_eq!(el.path.as_str(), "/org/a11y/atspi/accessible/null");
164}
165
166#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
168#[allow(clippy::module_name_repetitions)]
169pub enum EventListenerEvents {
170 Registered(EventListenerRegisteredEvent),
172 Deregistered(EventListenerDeregisteredEvent),
174}
175
176impl EventTypeProperties for EventListenerEvents {
177 fn member(&self) -> &'static str {
178 match self {
179 Self::Registered(inner) => inner.member(),
180 Self::Deregistered(inner) => inner.member(),
181 }
182 }
183 fn match_rule(&self) -> &'static str {
184 match self {
185 Self::Registered(inner) => inner.match_rule(),
186 Self::Deregistered(inner) => inner.match_rule(),
187 }
188 }
189 fn interface(&self) -> &'static str {
190 match self {
191 Self::Registered(inner) => inner.interface(),
192 Self::Deregistered(inner) => inner.interface(),
193 }
194 }
195 fn registry_string(&self) -> &'static str {
196 match self {
197 Self::Registered(inner) => inner.registry_string(),
198 Self::Deregistered(inner) => inner.registry_string(),
199 }
200 }
201}
202
203impl EventProperties for EventListenerEvents {
204 fn path(&self) -> ObjectPath<'_> {
205 match self {
206 Self::Registered(inner) => inner.path(),
207 Self::Deregistered(inner) => inner.path(),
208 }
209 }
210 fn sender(&self) -> UniqueName<'_> {
211 match self {
212 Self::Registered(inner) => inner.sender(),
213 Self::Deregistered(inner) => inner.sender(),
214 }
215 }
216}
217
218#[cfg(feature = "zbus")]
219impl EventWrapperMessageConversion for EventListenerEvents {
220 fn try_from_message_interface_checked(msg: &zbus::Message) -> Result<Self, AtspiError> {
221 let header = msg.header();
222 let member = header.member().ok_or(AtspiError::MissingMember)?;
223 match member.as_str() {
224 EventListenerRegisteredEvent::DBUS_MEMBER => Ok(EventListenerEvents::Registered(
225 EventListenerRegisteredEvent::from_message_unchecked(msg)?,
226 )),
227 EventListenerDeregisteredEvent::DBUS_MEMBER => Ok(EventListenerEvents::Deregistered(
228 EventListenerDeregisteredEvent::from_message_unchecked(msg)?,
229 )),
230 _ => Err(AtspiError::MemberMatch(format!(
231 "No member {} in {}",
232 member.as_str(),
233 Self::DBUS_INTERFACE
234 ))),
235 }
236 }
237}
238
239#[cfg(feature = "zbus")]
240impl TryFrom<&zbus::Message> for EventListenerEvents {
241 type Error = AtspiError;
242 fn try_from(msg: &zbus::Message) -> Result<Self, Self::Error> {
243 Self::try_from_message(msg)
244 }
245}
246
247#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default, Eq, Hash)]
250pub struct EventListenerDeregisteredEvent {
251 pub item: ObjectRef,
253 pub deregistered_event: EventListeners,
256}
257
258impl_from_user_facing_event_for_interface_event_enum!(
259 EventListenerDeregisteredEvent,
260 EventListenerEvents,
261 EventListenerEvents::Deregistered
262);
263impl_from_user_facing_type_for_event_enum!(EventListenerDeregisteredEvent, Event::Listener);
264impl_try_from_event_for_user_facing_type!(
265 EventListenerDeregisteredEvent,
266 EventListenerEvents::Deregistered,
267 Event::Listener
268);
269event_test_cases!(EventListenerDeregisteredEvent, Explicit);
270impl BusProperties for EventListenerDeregisteredEvent {
271 const REGISTRY_EVENT_STRING: &'static str = "Registry:EventListenerDeregistered";
272 const MATCH_RULE_STRING: &'static str =
273 "type='signal',interface='org.a11y.atspi.Registry',member='EventListenerDeregistered'";
274 const DBUS_MEMBER: &'static str = "EventListenerDeregistered";
275 const DBUS_INTERFACE: &'static str = "org.a11y.atspi.Registry";
276}
277
278#[cfg(feature = "zbus")]
279impl MessageConversion for EventListenerDeregisteredEvent {
280 type Body = EventListeners;
281
282 fn from_message_unchecked_parts(
283 item: ObjectRef,
284 deregistered_event: Self::Body,
285 ) -> Result<Self, AtspiError> {
286 Ok(Self { item, deregistered_event })
287 }
288 fn from_message_unchecked(msg: &zbus::Message) -> Result<Self, AtspiError> {
289 let item = msg.try_into()?;
290 let body = msg.body().deserialize()?;
291 Self::from_message_unchecked_parts(item, body)
292 }
293 fn body(&self) -> Self::Body {
294 self.deregistered_event.clone()
295 }
296}
297impl_from_dbus_message!(EventListenerDeregisteredEvent, Explicit);
298impl_event_properties!(EventListenerDeregisteredEvent);
299impl_to_dbus_message!(EventListenerDeregisteredEvent);
300
301#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default, Eq, Hash)]
303pub struct EventListenerRegisteredEvent {
304 pub item: ObjectRef,
306 pub registered_event: EventListeners,
309}
310
311impl_from_user_facing_event_for_interface_event_enum!(
312 EventListenerRegisteredEvent,
313 EventListenerEvents,
314 EventListenerEvents::Registered
315);
316impl_from_user_facing_type_for_event_enum!(EventListenerRegisteredEvent, Event::Listener);
317impl_try_from_event_for_user_facing_type!(
318 EventListenerRegisteredEvent,
319 EventListenerEvents::Registered,
320 Event::Listener
321);
322event_test_cases!(EventListenerRegisteredEvent, Explicit);
323impl BusProperties for EventListenerRegisteredEvent {
324 const REGISTRY_EVENT_STRING: &'static str = "Registry:EventListenerRegistered";
325 const MATCH_RULE_STRING: &'static str =
326 "type='signal',interface='org.a11y.atspi.Registry',member='EventListenerRegistered'";
327 const DBUS_MEMBER: &'static str = "EventListenerRegistered";
328 const DBUS_INTERFACE: &'static str = "org.a11y.atspi.Registry";
329}
330
331#[cfg(feature = "zbus")]
332impl MessageConversion for EventListenerRegisteredEvent {
333 type Body = EventListeners;
334
335 fn from_message_unchecked_parts(
336 item: ObjectRef,
337 registered_event: Self::Body,
338 ) -> Result<Self, AtspiError> {
339 Ok(Self { item, registered_event })
340 }
341 fn from_message_unchecked(msg: &zbus::Message) -> Result<Self, AtspiError> {
342 let item = msg.try_into()?;
343 let body = msg.body().deserialize()?;
344 Self::from_message_unchecked_parts(item, body)
345 }
346 fn body(&self) -> Self::Body {
347 self.registered_event.clone()
348 }
349}
350impl_from_dbus_message!(EventListenerRegisteredEvent, Explicit);
351impl_event_properties!(EventListenerRegisteredEvent);
352impl_to_dbus_message!(EventListenerRegisteredEvent);
353
354#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Default, Eq, Hash)]
356pub struct AvailableEvent {
357 pub item: ObjectRef,
359 pub socket: ObjectRef,
360}
361#[cfg(feature = "wrappers")]
362impl From<AvailableEvent> for Event {
363 fn from(ev: AvailableEvent) -> Event {
364 Event::Available(ev)
365 }
366}
367#[cfg(feature = "wrappers")]
368impl TryFrom<Event> for AvailableEvent {
369 type Error = AtspiError;
370 fn try_from(generic_event: Event) -> Result<AvailableEvent, Self::Error> {
371 if let Event::Available(specific_event) = generic_event {
372 Ok(specific_event)
373 } else {
374 Err(AtspiError::Conversion("Invalid type"))
375 }
376 }
377}
378event_test_cases!(AvailableEvent, Explicit);
379impl BusProperties for AvailableEvent {
380 const REGISTRY_EVENT_STRING: &'static str = "Socket:Available";
381 const MATCH_RULE_STRING: &'static str =
382 "type='signal',interface='org.a11y.atspi.Socket',member='Available'";
383 const DBUS_MEMBER: &'static str = "Available";
384 const DBUS_INTERFACE: &'static str = "org.a11y.atspi.Socket";
385}
386
387#[cfg(feature = "zbus")]
388impl MessageConversion for AvailableEvent {
389 type Body = ObjectRef;
390
391 fn from_message_unchecked_parts(
392 item: ObjectRef,
393 socket: Self::Body,
394 ) -> Result<Self, AtspiError> {
395 Ok(Self { item, socket })
396 }
397 fn from_message_unchecked(msg: &zbus::Message) -> Result<Self, AtspiError> {
398 let item = msg.try_into()?;
399 let body = msg.body().deserialize()?;
400 Self::from_message_unchecked_parts(item, body)
401 }
402 fn body(&self) -> Self::Body {
403 self.socket.clone()
404 }
405}
406impl_from_dbus_message!(AvailableEvent, Explicit);
407impl_event_properties!(AvailableEvent);
408impl_to_dbus_message!(AvailableEvent);
409
410#[cfg(all(feature = "zbus", feature = "wrappers"))]
411impl TryFrom<&zbus::Message> for Event {
412 type Error = AtspiError;
413
414 fn try_from(msg: &zbus::Message) -> Result<Event, AtspiError> {
415 let header = msg.header();
416 let interface = header.interface().ok_or(AtspiError::MissingInterface)?;
417 let interface_str = interface.as_str();
418
419 match interface_str {
420 <AvailableEvent as HasInterfaceName>::DBUS_INTERFACE => {
421 Ok(AvailableEvent::try_from(msg)?.into())
422 }
423 <ObjectEvents as HasInterfaceName>::DBUS_INTERFACE => {
424 Ok(Event::Object(ObjectEvents::try_from_message_interface_checked(msg)?))
425 }
426 <DocumentEvents as HasInterfaceName>::DBUS_INTERFACE => {
427 Ok(Event::Document(DocumentEvents::try_from_message_interface_checked(msg)?))
428 }
429 <WindowEvents as HasInterfaceName>::DBUS_INTERFACE => {
430 Ok(Event::Window(WindowEvents::try_from_message_interface_checked(msg)?))
431 }
432 <TerminalEvents as HasInterfaceName>::DBUS_INTERFACE => {
433 Ok(Event::Terminal(TerminalEvents::try_from_message_interface_checked(msg)?))
434 }
435 <MouseEvents as HasInterfaceName>::DBUS_INTERFACE => {
436 Ok(Event::Mouse(MouseEvents::try_from_message_interface_checked(msg)?))
437 }
438 <FocusEvents as HasInterfaceName>::DBUS_INTERFACE => {
439 Ok(Event::Focus(FocusEvents::try_from_message_interface_checked(msg)?))
440 }
441 <KeyboardEvents as HasInterfaceName>::DBUS_INTERFACE => {
442 Ok(Event::Keyboard(KeyboardEvents::try_from_message_interface_checked(msg)?))
443 }
444 <CacheEvents as HasInterfaceName>::DBUS_INTERFACE => {
445 Ok(Event::Cache(CacheEvents::try_from_message_interface_checked(msg)?))
446 }
447 <EventListenerEvents as HasInterfaceName>::DBUS_INTERFACE => {
448 Ok(Event::Listener(EventListenerEvents::try_from_message_interface_checked(msg)?))
449 }
450 _ => Err(AtspiError::InterfaceMatch(format!(
451 "No events found with interface {interface_str}"
452 ))),
453 }
454 }
455}
456
457impl<T: BusProperties> EventTypeProperties for T {
458 fn member(&self) -> &'static str {
459 <T>::DBUS_MEMBER
460 }
461 fn interface(&self) -> &'static str {
462 <T>::DBUS_INTERFACE
463 }
464 fn match_rule(&self) -> &'static str {
465 <T>::MATCH_RULE_STRING
466 }
467 fn registry_string(&self) -> &'static str {
468 <T>::REGISTRY_EVENT_STRING
469 }
470}
471
472assert_obj_safe!(EventTypeProperties);
473
474assert_obj_safe!(EventProperties);
475
476#[cfg(feature = "zbus")]
477impl<T> MessageConversionExt<crate::LegacyCacheItem> for T
478where
479 T: MessageConversion<Body = crate::LegacyCacheItem>,
480{
481 fn try_from_message(msg: &zbus::Message) -> Result<Self, AtspiError> {
482 <T as MessageConversionExt<crate::LegacyCacheItem>>::validate_interface(msg)?;
483 <T as MessageConversionExt<crate::LegacyCacheItem>>::validate_member(msg)?;
484 <T as MessageConversionExt<crate::LegacyCacheItem>>::validate_body(msg)?;
485 <T as MessageConversion>::from_message_unchecked(msg)
486 }
487}
488
489#[cfg(feature = "zbus")]
490impl<T> MessageConversionExt<EventListeners> for T
491where
492 T: MessageConversion<Body = EventListeners>,
493{
494 fn try_from_message(msg: &zbus::Message) -> Result<Self, AtspiError> {
495 <T as MessageConversionExt<EventListeners>>::validate_interface(msg)?;
496 <T as MessageConversionExt<EventListeners>>::validate_member(msg)?;
497 <T as MessageConversionExt<EventListeners>>::validate_body(msg)?;
498 <T as MessageConversion>::from_message_unchecked(msg)
499 }
500}
501
502#[cfg(feature = "zbus")]
503impl<T> MessageConversionExt<crate::CacheItem> for T
504where
505 T: MessageConversion<Body = crate::CacheItem>,
506{
507 fn try_from_message(msg: &zbus::Message) -> Result<Self, AtspiError> {
508 <T as MessageConversionExt<crate::CacheItem>>::validate_interface(msg)?;
509 <T as MessageConversionExt<crate::CacheItem>>::validate_member(msg)?;
510 <T as MessageConversionExt<crate::CacheItem>>::validate_body(msg)?;
511 <T as MessageConversion>::from_message_unchecked(msg)
512 }
513}
514
515#[cfg(feature = "zbus")]
516impl<T> MessageConversionExt<ObjectRef> for T
517where
518 T: MessageConversion<Body = ObjectRef>,
519{
520 fn try_from_message(msg: &zbus::Message) -> Result<Self, AtspiError> {
521 <T as MessageConversionExt<ObjectRef>>::validate_interface(msg)?;
522 <T as MessageConversionExt<ObjectRef>>::validate_member(msg)?;
523 <T as MessageConversionExt<ObjectRef>>::validate_body(msg)?;
524 <T as MessageConversion>::from_message_unchecked(msg)
525 }
526}
527
528#[cfg(feature = "zbus")]
529impl<T> MessageConversionExt<EventBodyOwned> for T
530where
531 T: MessageConversion<Body = EventBodyOwned>,
532{
533 fn try_from_message(msg: &zbus::Message) -> Result<Self, AtspiError> {
534 <T as MessageConversionExt<EventBodyOwned>>::validate_interface(msg)?;
535 <T as MessageConversionExt<EventBodyOwned>>::validate_member(msg)?;
536 let body = msg.body();
537 let body_sig = body.signature();
538 let data_body: EventBodyOwned = if body_sig == EventBodyOwned::SIGNATURE {
539 body.deserialize_unchecked()?
540 } else if body_sig == QSPI_EVENT_SIGNATURE {
541 let qtbody: EventBodyQtOwned = body.deserialize_unchecked()?;
542 qtbody.into()
543 } else {
544 return Err(AtspiError::SignatureMatch(format!(
545 "The message signature {} does not match the signal's body signature: {} or {}",
546 body_sig,
547 EventBodyOwned::SIGNATURE,
548 EventBodyQtOwned::SIGNATURE,
549 )));
550 };
551 let item = msg.try_into()?;
552 Self::from_message_unchecked_parts(item, data_body)
553 }
554}
555
556#[cfg(feature = "zbus")]
557impl<T: EventWrapperMessageConversion + HasInterfaceName> TryFromMessage for T {
558 fn try_from_message(msg: &zbus::Message) -> Result<T, AtspiError> {
559 let header = msg.header();
560 let interface = header.interface().ok_or(AtspiError::MissingInterface)?;
561 if interface != <T as HasInterfaceName>::DBUS_INTERFACE {
562 return Err(AtspiError::InterfaceMatch(format!(
563 "Interface {} does not match require interface for event: {}",
564 interface,
565 <T as HasInterfaceName>::DBUS_INTERFACE
566 )));
567 }
568 <T as EventWrapperMessageConversion>::try_from_message_interface_checked(msg)
569 }
570}