1pub mod document;
2pub mod focus;
3pub mod keyboard;
4pub mod mouse;
5pub mod object;
6pub mod terminal;
7pub mod window;
8
9pub const ATSPI_EVENT_SIGNATURE: Signature<'_> =
21 Signature::from_static_str_unchecked("(siiva{sv})");
22pub const QSPI_EVENT_SIGNATURE: Signature<'_> = Signature::from_static_str_unchecked("(siiv(so))");
23pub const EVENT_LISTENER_SIGNATURE: Signature<'_> = Signature::from_static_str_unchecked("(ss)");
24pub const CACHE_ADD_SIGNATURE: Signature<'_> =
25 Signature::from_static_str_unchecked("((so)(so)(so)iiassusau)");
26
27use std::collections::HashMap;
28
29use serde::{Deserialize, Serialize};
30use zbus_lockstep_macros::validate;
31use zbus_names::{OwnedUniqueName, UniqueName};
32#[cfg(feature = "zbus")]
33use zvariant::OwnedObjectPath;
34use zvariant::{ObjectPath, OwnedValue, Signature, Type, Value};
35
36use crate::{
37 cache::{CacheItem, LegacyCacheItem},
38 events::{
39 document::DocumentEvents, focus::FocusEvents, keyboard::KeyboardEvents, mouse::MouseEvents,
40 object::ObjectEvents, terminal::TerminalEvents, window::WindowEvents,
41 },
42 AtspiError, ObjectRef,
43};
44
45#[derive(Debug, Serialize, Deserialize)]
47pub struct EventBody<'a, T> {
48 #[serde(rename = "type")]
51 pub kind: T,
52 pub detail1: i32,
54 pub detail2: i32,
56 #[serde(borrow)]
59 pub any_data: Value<'a>,
60 #[serde(borrow)]
63 pub properties: HashMap<UniqueName<'a>, Value<'a>>,
64}
65
66impl<T> Type for EventBody<'_, T> {
67 fn signature() -> Signature<'static> {
68 <(&str, i32, i32, Value, HashMap<&str, Value>)>::signature()
69 }
70}
71
72#[derive(Debug, Serialize, Deserialize, Type)]
75pub struct EventBodyQT {
76 pub kind: String,
80 pub detail1: i32,
82 pub detail2: i32,
84 pub any_data: OwnedValue,
87 pub properties: ObjectRef,
90}
91
92impl Default for EventBodyQT {
93 fn default() -> Self {
94 Self {
95 kind: String::new(),
96 detail1: 0,
97 detail2: 0,
98 any_data: 0u8.into(),
99 properties: ObjectRef::default(),
100 }
101 }
102}
103
104#[validate(signal: "PropertyChange")]
108#[derive(Debug, Serialize, Deserialize, Type, PartialEq)]
109pub struct EventBodyOwned {
110 #[serde(rename = "type")]
113 pub kind: String,
114 pub detail1: i32,
116 pub detail2: i32,
118 pub any_data: OwnedValue,
121 pub properties: HashMap<OwnedUniqueName, OwnedValue>,
124}
125
126impl From<EventBodyQT> for EventBodyOwned {
127 fn from(body: EventBodyQT) -> Self {
128 let mut props = HashMap::new();
129
130 let name = body.properties.name;
131 let path = body.properties.path;
132
133 let value = Value::ObjectPath(path.into()).try_to_owned().unwrap_or_else(|err| {
137 panic!("Error occurred: {err:?}");
138 });
139
140 props.insert(name, value);
141 Self {
142 kind: body.kind,
143 detail1: body.detail1,
144 detail2: body.detail2,
145 any_data: body.any_data,
146 properties: props,
147 }
148 }
149}
150
151impl Default for EventBodyOwned {
152 fn default() -> Self {
153 Self {
154 kind: String::new(),
155 detail1: 0,
156 detail2: 0,
157 any_data: 0u8.into(),
158 properties: HashMap::new(),
159 }
160 }
161}
162
163impl Clone for EventBodyOwned {
176 fn clone(&self) -> Self {
177 let cloned_any_data = self.any_data.try_clone().unwrap_or_else(|err| {
178 panic!("Failure cloning 'any_data' field: {err:?}");
179 });
180
181 let cloned_properties = {
182 let mut map = HashMap::new();
183 for (key, value) in &self.properties {
184 let cloned_value = value.try_clone().unwrap_or_else(|err| {
185 panic!("Failure cloning 'props' field: {err:?}");
186 });
187 map.insert(key.clone(), cloned_value);
188 }
189 map
190 };
191
192 Self {
193 kind: self.kind.clone(),
194 detail1: self.detail1,
195 detail2: self.detail2,
196 any_data: cloned_any_data,
197 properties: cloned_properties,
198 }
199 }
200}
201
202#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
206#[non_exhaustive]
207pub enum Event {
208 Document(DocumentEvents),
210 Focus(FocusEvents),
212 Keyboard(KeyboardEvents),
214 Mouse(MouseEvents),
216 Object(ObjectEvents),
218 Terminal(TerminalEvents),
220 Window(WindowEvents),
222 Available(AvailableEvent),
224 Cache(CacheEvents),
226 Listener(EventListenerEvents),
228}
229
230impl EventTypeProperties for Event {
231 fn member(&self) -> &'static str {
232 match self {
233 Self::Document(inner) => inner.member(),
234 Self::Focus(inner) => inner.member(),
235 Self::Keyboard(inner) => inner.member(),
236 Self::Mouse(inner) => inner.member(),
237 Self::Object(inner) => inner.member(),
238 Self::Terminal(inner) => inner.member(),
239 Self::Window(inner) => inner.member(),
240 Self::Available(inner) => inner.member(),
241 Self::Cache(inner) => inner.member(),
242 Self::Listener(inner) => inner.member(),
243 }
244 }
245 fn interface(&self) -> &'static str {
246 match self {
247 Self::Document(inner) => inner.interface(),
248 Self::Focus(inner) => inner.interface(),
249 Self::Keyboard(inner) => inner.interface(),
250 Self::Mouse(inner) => inner.interface(),
251 Self::Object(inner) => inner.interface(),
252 Self::Terminal(inner) => inner.interface(),
253 Self::Window(inner) => inner.interface(),
254 Self::Available(inner) => inner.interface(),
255 Self::Cache(inner) => inner.interface(),
256 Self::Listener(inner) => inner.interface(),
257 }
258 }
259 fn match_rule(&self) -> &'static str {
260 match self {
261 Self::Document(inner) => inner.match_rule(),
262 Self::Focus(inner) => inner.match_rule(),
263 Self::Keyboard(inner) => inner.match_rule(),
264 Self::Mouse(inner) => inner.match_rule(),
265 Self::Object(inner) => inner.match_rule(),
266 Self::Terminal(inner) => inner.match_rule(),
267 Self::Window(inner) => inner.match_rule(),
268 Self::Available(inner) => inner.match_rule(),
269 Self::Cache(inner) => inner.match_rule(),
270 Self::Listener(inner) => inner.match_rule(),
271 }
272 }
273 fn registry_string(&self) -> &'static str {
274 match self {
275 Self::Document(inner) => inner.registry_string(),
276 Self::Focus(inner) => inner.registry_string(),
277 Self::Keyboard(inner) => inner.registry_string(),
278 Self::Mouse(inner) => inner.registry_string(),
279 Self::Object(inner) => inner.registry_string(),
280 Self::Terminal(inner) => inner.registry_string(),
281 Self::Window(inner) => inner.registry_string(),
282 Self::Available(inner) => inner.registry_string(),
283 Self::Cache(inner) => inner.registry_string(),
284 Self::Listener(inner) => inner.registry_string(),
285 }
286 }
287}
288
289impl EventProperties for Event {
290 fn path(&self) -> ObjectPath<'_> {
291 match self {
292 Self::Document(inner) => inner.path(),
293 Self::Focus(inner) => inner.path(),
294 Self::Keyboard(inner) => inner.path(),
295 Self::Mouse(inner) => inner.path(),
296 Self::Object(inner) => inner.path(),
297 Self::Terminal(inner) => inner.path(),
298 Self::Window(inner) => inner.path(),
299 Self::Available(inner) => inner.path(),
300 Self::Cache(inner) => inner.path(),
301 Self::Listener(inner) => inner.path(),
302 }
303 }
304 fn sender(&self) -> UniqueName<'_> {
305 match self {
306 Self::Document(inner) => inner.sender(),
307 Self::Focus(inner) => inner.sender(),
308 Self::Keyboard(inner) => inner.sender(),
309 Self::Mouse(inner) => inner.sender(),
310 Self::Object(inner) => inner.sender(),
311 Self::Terminal(inner) => inner.sender(),
312 Self::Window(inner) => inner.sender(),
313 Self::Available(inner) => inner.sender(),
314 Self::Cache(inner) => inner.sender(),
315 Self::Listener(inner) => inner.sender(),
316 }
317 }
318}
319
320impl HasMatchRule for CacheEvents {
321 const MATCH_RULE_STRING: &'static str = "type='signal',interface='org.a11y.atspi.Event.Cache'";
322}
323
324impl HasRegistryEventString for CacheEvents {
325 const REGISTRY_EVENT_STRING: &'static str = "Cache";
326}
327
328impl HasMatchRule for EventListenerEvents {
329 const MATCH_RULE_STRING: &'static str =
330 "type='signal',interface='org.a11y.atspi.Event.Registry'";
331}
332
333impl HasRegistryEventString for EventListenerEvents {
334 const REGISTRY_EVENT_STRING: &'static str = "Event";
335}
336
337#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Eq, Hash)]
341#[allow(clippy::module_name_repetitions)]
342pub enum CacheEvents {
343 Add(AddAccessibleEvent),
345 LegacyAdd(LegacyAddAccessibleEvent),
347 Remove(RemoveAccessibleEvent),
349}
350
351impl EventTypeProperties for CacheEvents {
352 fn member(&self) -> &'static str {
353 match self {
354 Self::Add(inner) => inner.member(),
355 Self::LegacyAdd(inner) => inner.member(),
356 Self::Remove(inner) => inner.member(),
357 }
358 }
359 fn interface(&self) -> &'static str {
360 match self {
361 Self::Add(inner) => inner.interface(),
362 Self::LegacyAdd(inner) => inner.interface(),
363 Self::Remove(inner) => inner.interface(),
364 }
365 }
366 fn match_rule(&self) -> &'static str {
367 match self {
368 Self::Add(inner) => inner.match_rule(),
369 Self::LegacyAdd(inner) => inner.match_rule(),
370 Self::Remove(inner) => inner.match_rule(),
371 }
372 }
373 fn registry_string(&self) -> &'static str {
374 match self {
375 Self::Add(inner) => inner.registry_string(),
376 Self::LegacyAdd(inner) => inner.registry_string(),
377 Self::Remove(inner) => inner.registry_string(),
378 }
379 }
380}
381
382impl EventProperties for CacheEvents {
383 fn path(&self) -> ObjectPath<'_> {
384 match self {
385 Self::Add(inner) => inner.path(),
386 Self::LegacyAdd(inner) => inner.path(),
387 Self::Remove(inner) => inner.path(),
388 }
389 }
390 fn sender(&self) -> UniqueName<'_> {
391 match self {
392 Self::Add(inner) => inner.sender(),
393 Self::LegacyAdd(inner) => inner.sender(),
394 Self::Remove(inner) => inner.sender(),
395 }
396 }
397}
398
399#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default, Eq, Hash)]
402pub struct LegacyAddAccessibleEvent {
403 pub item: ObjectRef,
405 pub node_added: LegacyCacheItem,
407}
408
409impl_from_user_facing_event_for_interface_event_enum!(
410 LegacyAddAccessibleEvent,
411 CacheEvents,
412 CacheEvents::LegacyAdd
413);
414impl_from_user_facing_type_for_event_enum!(LegacyAddAccessibleEvent, Event::Cache);
415impl_try_from_event_for_user_facing_type!(
416 LegacyAddAccessibleEvent,
417 CacheEvents::LegacyAdd,
418 Event::Cache
419);
420event_test_cases!(LegacyAddAccessibleEvent);
421impl_from_dbus_message!(LegacyAddAccessibleEvent);
422impl_event_properties!(LegacyAddAccessibleEvent);
423impl_to_dbus_message!(LegacyAddAccessibleEvent);
424
425impl BusProperties for LegacyAddAccessibleEvent {
426 const REGISTRY_EVENT_STRING: &'static str = "Cache:Add";
427 const MATCH_RULE_STRING: &'static str =
428 "type='signal',interface='org.a11y.atspi.Cache',member='AddAccessible'";
429 const DBUS_MEMBER: &'static str = "AddAccessible";
430 const DBUS_INTERFACE: &'static str = "org.a11y.atspi.Cache";
431
432 type Body = LegacyCacheItem;
433
434 fn from_message_parts(item: ObjectRef, body: Self::Body) -> Result<Self, AtspiError> {
435 Ok(Self { item, node_added: body })
436 }
437
438 fn body(&self) -> Self::Body {
439 self.node_added.clone()
440 }
441}
442
443#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default, Eq, Hash)]
446pub struct AddAccessibleEvent {
447 pub item: ObjectRef,
449 pub node_added: CacheItem,
451}
452
453impl_from_user_facing_event_for_interface_event_enum!(
454 AddAccessibleEvent,
455 CacheEvents,
456 CacheEvents::Add
457);
458impl_from_user_facing_type_for_event_enum!(AddAccessibleEvent, Event::Cache);
459impl_try_from_event_for_user_facing_type!(AddAccessibleEvent, CacheEvents::Add, Event::Cache);
460event_test_cases!(AddAccessibleEvent);
461
462impl BusProperties for AddAccessibleEvent {
463 const REGISTRY_EVENT_STRING: &'static str = "Cache:Add";
464 const MATCH_RULE_STRING: &'static str =
465 "type='signal',interface='org.a11y.atspi.Cache',member='AddAccessible'";
466 const DBUS_MEMBER: &'static str = "AddAccessible";
467 const DBUS_INTERFACE: &'static str = "org.a11y.atspi.Cache";
468
469 type Body = CacheItem;
470
471 fn from_message_parts(item: ObjectRef, body: Self::Body) -> Result<Self, AtspiError> {
472 Ok(Self { item, node_added: body })
473 }
474
475 fn body(&self) -> Self::Body {
476 self.node_added.clone()
477 }
478}
479impl<T: BusProperties> HasMatchRule for T {
480 const MATCH_RULE_STRING: &'static str = <T as BusProperties>::MATCH_RULE_STRING;
481}
482impl<T: BusProperties> HasRegistryEventString for T {
483 const REGISTRY_EVENT_STRING: &'static str = <T as BusProperties>::REGISTRY_EVENT_STRING;
484}
485impl_from_dbus_message!(AddAccessibleEvent);
486impl_event_properties!(AddAccessibleEvent);
487impl_to_dbus_message!(AddAccessibleEvent);
488
489#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default, Eq, Hash)]
491pub struct RemoveAccessibleEvent {
492 pub item: ObjectRef,
495 pub node_removed: ObjectRef,
497}
498
499impl_from_user_facing_event_for_interface_event_enum!(
500 RemoveAccessibleEvent,
501 CacheEvents,
502 CacheEvents::Remove
503);
504impl_from_user_facing_type_for_event_enum!(RemoveAccessibleEvent, Event::Cache);
505impl_try_from_event_for_user_facing_type!(RemoveAccessibleEvent, CacheEvents::Remove, Event::Cache);
506event_test_cases!(RemoveAccessibleEvent);
507impl BusProperties for RemoveAccessibleEvent {
508 const REGISTRY_EVENT_STRING: &'static str = "Cache:Remove";
509 const MATCH_RULE_STRING: &'static str =
510 "type='signal',interface='org.a11y.atspi.Cache',member='RemoveAccessible'";
511 const DBUS_MEMBER: &'static str = "RemoveAccessible";
512 const DBUS_INTERFACE: &'static str = "org.a11y.atspi.Cache";
513
514 type Body = ObjectRef;
515
516 fn from_message_parts(item: ObjectRef, body: Self::Body) -> Result<Self, AtspiError> {
517 Ok(Self { item, node_removed: body })
518 }
519 fn body(&self) -> Self::Body {
520 self.node_removed.clone()
521 }
522}
523
524impl_from_dbus_message!(RemoveAccessibleEvent);
525impl_event_properties!(RemoveAccessibleEvent);
526impl_to_dbus_message!(RemoveAccessibleEvent);
527
528#[cfg(test)]
529mod accessible_deserialization_tests {
530 use crate::events::ObjectRef;
531 use zvariant::Value;
532
533 #[test]
534 fn try_into_value() {
535 let acc = ObjectRef::default();
536 let value_struct = Value::from(acc);
537 let Value::Structure(structure) = value_struct else {
538 panic!("Unable to destructure a structure out of the Value.");
539 };
540 let vals = structure.into_fields();
541 assert_eq!(vals.len(), 2);
542 let Value::Str(bus_name) = vals.first().unwrap() else {
543 panic!("Unable to destructure field value: {:?}", vals.first().unwrap());
544 };
545 assert_eq!(bus_name, ":0.0");
546 let Value::ObjectPath(path) = vals.last().unwrap() else {
547 panic!("Unable to destructure field value: {:?}", vals.get(1).unwrap());
548 };
549 assert_eq!(path.as_str(), "/org/a11y/atspi/accessible/null");
550 }
551 #[test]
552 fn try_from_value() {}
553}
554
555#[cfg(test)]
556mod accessible_tests {
557 use super::ObjectRef;
558
559 #[test]
560 fn test_accessible_default_doesnt_panic() {
561 let acc = ObjectRef::default();
562 assert_eq!(acc.name.as_str(), ":0.0");
563 assert_eq!(acc.path.as_str(), "/org/a11y/atspi/accessible/null");
564 }
565}
566#[cfg(feature = "zbus")]
567impl TryFrom<&zbus::Message> for ObjectRef {
568 type Error = AtspiError;
569 fn try_from(message: &zbus::Message) -> Result<Self, Self::Error> {
570 let header = message.header();
571 let path = header.path().expect("returned path is either `Some` or panics");
572 let owned_path: OwnedObjectPath = path.clone().into();
573
574 let sender: UniqueName<'_> = header.sender().expect("No sender in header").into();
575 let name: OwnedUniqueName = sender.to_owned().into();
576
577 Ok(ObjectRef { name, path: owned_path })
578 }
579}
580
581#[cfg(feature = "zbus")]
582impl TryFrom<&zbus::Message> for EventBodyOwned {
583 type Error = AtspiError;
584
585 fn try_from(message: &zbus::Message) -> Result<Self, Self::Error> {
586 let body = message.body();
587 let signature = body.signature().ok_or_else(|| AtspiError::MissingSignature)?;
588
589 if signature == QSPI_EVENT_SIGNATURE {
590 let qt_body = body.deserialize::<EventBodyQT>()?;
591 Ok(EventBodyOwned::from(qt_body))
592 } else if signature == ATSPI_EVENT_SIGNATURE {
593 Ok(body.deserialize::<EventBodyOwned>()?)
594 } else {
595 Err(AtspiError::Conversion(
596 "Unable to convert from zbus::Message to EventBodyQT or EventBodyOwned",
597 ))
598 }
599 }
600}
601
602#[validate(signal: "EventListenerRegistered")]
605#[derive(Debug, Clone, Serialize, Deserialize, Type, PartialEq, Eq, Hash)]
606pub struct EventListeners {
607 pub bus_name: OwnedUniqueName,
608 pub path: String,
609}
610
611impl Default for EventListeners {
612 fn default() -> Self {
613 Self {
614 bus_name: UniqueName::try_from(":0.0").unwrap().into(),
615 path: "/org/a11y/atspi/accessible/null".to_string(),
616 }
617 }
618}
619
620#[cfg(test)]
621#[test]
622fn test_event_listener_default_no_panic() {
623 let el = EventListeners::default();
624 assert_eq!(el.bus_name.as_str(), ":0.0");
625 assert_eq!(el.path.as_str(), "/org/a11y/atspi/accessible/null");
626}
627
628#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
630#[allow(clippy::module_name_repetitions)]
631pub enum EventListenerEvents {
632 Registered(EventListenerRegisteredEvent),
634 Deregistered(EventListenerDeregisteredEvent),
636}
637
638impl EventTypeProperties for EventListenerEvents {
639 fn member(&self) -> &'static str {
640 match self {
641 Self::Registered(inner) => inner.member(),
642 Self::Deregistered(inner) => inner.member(),
643 }
644 }
645 fn match_rule(&self) -> &'static str {
646 match self {
647 Self::Registered(inner) => inner.match_rule(),
648 Self::Deregistered(inner) => inner.match_rule(),
649 }
650 }
651 fn interface(&self) -> &'static str {
652 match self {
653 Self::Registered(inner) => inner.interface(),
654 Self::Deregistered(inner) => inner.interface(),
655 }
656 }
657 fn registry_string(&self) -> &'static str {
658 match self {
659 Self::Registered(inner) => inner.registry_string(),
660 Self::Deregistered(inner) => inner.registry_string(),
661 }
662 }
663}
664
665impl EventProperties for EventListenerEvents {
666 fn path(&self) -> ObjectPath<'_> {
667 match self {
668 Self::Registered(inner) => inner.path(),
669 Self::Deregistered(inner) => inner.path(),
670 }
671 }
672 fn sender(&self) -> UniqueName<'_> {
673 match self {
674 Self::Registered(inner) => inner.sender(),
675 Self::Deregistered(inner) => inner.sender(),
676 }
677 }
678}
679
680#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default, Eq, Hash)]
683pub struct EventListenerDeregisteredEvent {
684 pub item: ObjectRef,
686 pub deregistered_event: EventListeners,
689}
690
691impl_from_user_facing_event_for_interface_event_enum!(
692 EventListenerDeregisteredEvent,
693 EventListenerEvents,
694 EventListenerEvents::Deregistered
695);
696impl_from_user_facing_type_for_event_enum!(EventListenerDeregisteredEvent, Event::Listener);
697impl_try_from_event_for_user_facing_type!(
698 EventListenerDeregisteredEvent,
699 EventListenerEvents::Deregistered,
700 Event::Listener
701);
702event_test_cases!(EventListenerDeregisteredEvent);
703impl BusProperties for EventListenerDeregisteredEvent {
704 const REGISTRY_EVENT_STRING: &'static str = "Registry:EventListenerDeregistered";
705 const MATCH_RULE_STRING: &'static str =
706 "type='signal',interface='org.a11y.atspi.Registry',member='EventListenerDeregistered'";
707 const DBUS_MEMBER: &'static str = "EventListenerDeregistered";
708 const DBUS_INTERFACE: &'static str = "org.a11y.atspi.Registry";
709
710 type Body = EventListeners;
711
712 fn from_message_parts(item: ObjectRef, body: Self::Body) -> Result<Self, AtspiError> {
713 Ok(Self { item, deregistered_event: body })
714 }
715 fn body(&self) -> Self::Body {
716 self.deregistered_event.clone()
717 }
718}
719impl_from_dbus_message!(EventListenerDeregisteredEvent);
720impl_event_properties!(EventListenerDeregisteredEvent);
721impl_to_dbus_message!(EventListenerDeregisteredEvent);
722
723#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default, Eq, Hash)]
725pub struct EventListenerRegisteredEvent {
726 pub item: ObjectRef,
728 pub registered_event: EventListeners,
731}
732
733impl_from_user_facing_event_for_interface_event_enum!(
734 EventListenerRegisteredEvent,
735 EventListenerEvents,
736 EventListenerEvents::Registered
737);
738impl_from_user_facing_type_for_event_enum!(EventListenerRegisteredEvent, Event::Listener);
739impl_try_from_event_for_user_facing_type!(
740 EventListenerRegisteredEvent,
741 EventListenerEvents::Registered,
742 Event::Listener
743);
744event_test_cases!(EventListenerRegisteredEvent);
745impl BusProperties for EventListenerRegisteredEvent {
746 const REGISTRY_EVENT_STRING: &'static str = "Registry:EventListenerRegistered";
747 const MATCH_RULE_STRING: &'static str =
748 "type='signal',interface='org.a11y.atspi.Registry',member='EventListenerRegistered'";
749 const DBUS_MEMBER: &'static str = "EventListenerRegistered";
750 const DBUS_INTERFACE: &'static str = "org.a11y.atspi.Registry";
751
752 type Body = EventListeners;
753
754 fn from_message_parts(item: ObjectRef, body: Self::Body) -> Result<Self, AtspiError> {
755 Ok(Self { item, registered_event: body })
756 }
757 fn body(&self) -> Self::Body {
758 self.registered_event.clone()
759 }
760}
761impl_from_dbus_message!(EventListenerRegisteredEvent);
762impl_event_properties!(EventListenerRegisteredEvent);
763impl_to_dbus_message!(EventListenerRegisteredEvent);
764
765#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Default, Eq, Hash)]
767pub struct AvailableEvent {
768 pub item: ObjectRef,
770 pub socket: ObjectRef,
771}
772impl From<AvailableEvent> for Event {
773 fn from(ev: AvailableEvent) -> Event {
774 Event::Available(ev)
775 }
776}
777impl TryFrom<Event> for AvailableEvent {
778 type Error = AtspiError;
779 fn try_from(generic_event: Event) -> Result<AvailableEvent, Self::Error> {
780 if let Event::Available(specific_event) = generic_event {
781 Ok(specific_event)
782 } else {
783 Err(AtspiError::Conversion("Invalid type"))
784 }
785 }
786}
787event_test_cases!(AvailableEvent);
788impl BusProperties for AvailableEvent {
789 const REGISTRY_EVENT_STRING: &'static str = "Socket:Available";
790 const MATCH_RULE_STRING: &'static str =
791 "type='signal',interface='org.a11y.atspi.Socket',member='Available'";
792 const DBUS_MEMBER: &'static str = "Available";
793 const DBUS_INTERFACE: &'static str = "org.a11y.atspi.Socket";
794
795 type Body = ObjectRef;
796
797 fn from_message_parts(item: ObjectRef, body: Self::Body) -> Result<Self, AtspiError> {
798 Ok(Self { item, socket: body })
799 }
800 fn body(&self) -> Self::Body {
801 self.socket.clone()
802 }
803}
804impl_from_dbus_message!(AvailableEvent);
805impl_event_properties!(AvailableEvent);
806impl_to_dbus_message!(AvailableEvent);
807
808#[cfg(feature = "zbus")]
809impl TryFrom<&zbus::Message> for Event {
810 type Error = AtspiError;
811
812 fn try_from(msg: &zbus::Message) -> Result<Event, AtspiError> {
813 let body = msg.body();
814 let header = msg.header();
815
816 let body_signature = body.signature().ok_or(AtspiError::MissingSignature)?;
817 let body_signature_str = body_signature.as_str();
818
819 let member = header.member().ok_or(AtspiError::MissingMember)?;
820 let member_str = member.as_str();
821
822 let interface = header.interface().ok_or(AtspiError::MissingInterface)?;
823 let interface_str = interface.as_str();
824
825 match (interface_str, member_str, body_signature_str) {
830 ("org.a11y.atspi.Socket", "Available", "so") => {
831 Ok(AvailableEvent::try_from(msg)?.into())
832 }
833 ("org.a11y.atspi.Event.Object", _, "siiva{sv}" | "siiv(so)") => {
834 Ok(Event::Object(ObjectEvents::try_from(msg)?))
835 }
836 ("org.a11y.atspi.Event.Document", _, "siiva{sv}" | "siiv(so)") => {
837 Ok(Event::Document(DocumentEvents::try_from(msg)?))
838 }
839 ("org.a11y.atspi.Event.Window", _, "siiva{sv}" | "siiv(so)") => {
840 Ok(Event::Window(WindowEvents::try_from(msg)?))
841 }
842 ("org.a11y.atspi.Event.Terminal", _, "siiva{sv}" | "siiv(so)") => {
843 Ok(Event::Terminal(TerminalEvents::try_from(msg)?))
844 }
845 ("org.a11y.atspi.Event.Mouse", _, "siiva{sv}" | "siiv(so)") => {
846 Ok(Event::Mouse(MouseEvents::try_from(msg)?))
847 }
848 ("org.a11y.atspi.Event.Focus", _, "siiva{sv}" | "siiv(so)") => {
849 Ok(Event::Focus(FocusEvents::try_from(msg)?))
850 }
851 ("org.a11y.atspi.Event.Keyboard", _, "siiva{sv}" | "siiv(so)") => {
852 Ok(Event::Keyboard(KeyboardEvents::try_from(msg)?))
853 }
854 ("org.a11y.atspi.Registry", "EventListenerRegistered", "ss") => {
855 Ok(EventListenerRegisteredEvent::try_from(msg)?.into())
856 }
857 ("org.a11y.atspi.Registry", "EventListenerDeregistered", "ss") => {
858 Ok(EventListenerDeregisteredEvent::try_from(msg)?.into())
859 }
860 (
861 "org.a11y.atspi.Cache",
862 "AddAccessible",
863 "(so)(so)(so)iiassusau" | "((so)(so)(so)iiassusau)",
864 ) => Ok(AddAccessibleEvent::try_from(msg)?.into()),
865 (
866 "org.a11y.atspi.Cache",
867 "AddAccessible",
868 "(so)(so)(so)a(so)assusau" | "((so)(so)(so)a(so)assusau)",
869 ) => Ok(LegacyAddAccessibleEvent::try_from(msg)?.into()),
870 ("org.a11y.atspi.Cache", "RemoveAccessible", "so" | "(so)") => {
871 Ok(RemoveAccessibleEvent::try_from(msg)?.into())
872 }
873 (_iface, _method, sig) => Err(AtspiError::UnknownBusSignature(sig.to_string())),
874 }
875 }
876}
877
878pub trait EventTypeProperties {
892 fn member(&self) -> &'static str;
893 fn interface(&self) -> &'static str;
894 fn match_rule(&self) -> &'static str;
895 fn registry_string(&self) -> &'static str;
896}
897
898impl<T: BusProperties> EventTypeProperties for T {
899 fn member(&self) -> &'static str {
900 <T>::DBUS_MEMBER
901 }
902 fn interface(&self) -> &'static str {
903 <T>::DBUS_INTERFACE
904 }
905 fn match_rule(&self) -> &'static str {
906 <T>::MATCH_RULE_STRING
907 }
908 fn registry_string(&self) -> &'static str {
909 <T>::REGISTRY_EVENT_STRING
910 }
911}
912
913assert_obj_safe!(EventTypeProperties);
914
915pub trait EventProperties {
923 fn sender(&self) -> UniqueName<'_>;
924 fn path(&self) -> ObjectPath<'_>;
925 fn object_ref(&self) -> ObjectRef {
926 ObjectRef { name: self.sender().into(), path: self.path().into() }
927 }
928}
929
930assert_obj_safe!(EventProperties);
931
932pub trait BusProperties {
942 const DBUS_MEMBER: &'static str;
945 const DBUS_INTERFACE: &'static str;
948 const MATCH_RULE_STRING: &'static str;
952 const REGISTRY_EVENT_STRING: &'static str;
955
956 type Body: Type + Serialize + for<'a> Deserialize<'a>;
958
959 fn from_message_parts(item: ObjectRef, body: Self::Body) -> Result<Self, AtspiError>
966 where
967 Self: Sized;
968
969 fn body(&self) -> Self::Body;
971}
972
973pub trait HasMatchRule {
980 const MATCH_RULE_STRING: &'static str;
984}
985
986pub trait HasRegistryEventString {
993 const REGISTRY_EVENT_STRING: &'static str;
996}
997
998#[cfg(test)]
999mod tests {
1000 use super::{EventBodyOwned, EventBodyQT, QSPI_EVENT_SIGNATURE};
1001 use std::collections::HashMap;
1002 use zvariant::{ObjectPath, Type};
1003
1004 #[test]
1005 fn check_event_body_qt_signature() {
1006 assert_eq!(&<EventBodyQT as Type>::signature(), &QSPI_EVENT_SIGNATURE);
1007 }
1008
1009 #[test]
1010 fn test_event_body_qt_to_event_body_owned_conversion() {
1011 let event_body: EventBodyOwned = EventBodyQT::default().into();
1012
1013 let accessible = crate::ObjectRef::default();
1014 let name = accessible.name;
1015 let path = accessible.path;
1016 let props = HashMap::from([(name, ObjectPath::from(path).into())]);
1017 assert_eq!(event_body.properties, props);
1018 }
1019}