atspi_common/events/
object.rs

1use std::hash::Hash;
2
3#[cfg(feature = "zbus")]
4use crate::events::{MessageConversion, MessageConversionExt};
5use crate::{
6	error::AtspiError,
7	events::{BusProperties, EventBodyOwned, ObjectRef},
8	EventProperties, State,
9};
10use zbus_names::UniqueName;
11use zvariant::{ObjectPath, OwnedValue, Value};
12
13use super::{event_body::Properties, EventBodyQtOwned};
14
15/// The `org.a11y.atspi.Event.Object:PropertyChange` event.
16#[derive(Clone, Debug, PartialEq, serde::Serialize, serde::Deserialize)]
17pub struct PropertyChangeEvent {
18	/// The [`crate::ObjectRef`] which the event applies to.
19	pub item: crate::events::ObjectRef,
20	// TODO: this is not necessary since the string is encoded in the `Property` type.
21	pub property: String,
22	pub value: Property,
23}
24
25impl Hash for PropertyChangeEvent {
26	fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
27		self.item.hash(state);
28		self.property.hash(state);
29	}
30}
31
32// Do not derive Eq if not all fields implement Eq
33impl Eq for PropertyChangeEvent {}
34
35// Looks like a false positive Clippy lint
36#[allow(clippy::derivable_impls)]
37impl Default for PropertyChangeEvent {
38	fn default() -> Self {
39		Self { item: ObjectRef::default(), property: String::default(), value: Property::default() }
40	}
41}
42
43/// Any accessibility related property on an [`crate::ObjectRef`].
44/// This is used only in the [`PropertyChangeEvent`]; this event gets triggered if a role or accessible
45/// description of an item changes.
46#[derive(Debug, PartialEq, serde::Serialize, serde::Deserialize)]
47#[non_exhaustive]
48pub enum Property {
49	Name(String),
50	Description(String),
51	Role(crate::Role),
52	Parent(ObjectRef),
53	TableCaption(String),
54	TableColumnDescription(String),
55	TableColumnHeader(String),
56	TableRowDescription(String),
57	TableRowHeader(String),
58	TableSummary(String),
59	Other((String, OwnedValue)),
60}
61
62impl Clone for Property {
63	fn clone(&self) -> Self {
64		match self {
65			Property::Name(name) => Self::Name(name.clone()),
66			Property::Description(description) => Self::Description(description.clone()),
67			Property::Role(role) => Self::Role(*role),
68			Property::Parent(parent) => Self::Parent(parent.clone()),
69			Property::TableCaption(table_caption) => Self::TableCaption(table_caption.clone()),
70			Property::TableColumnDescription(table_column_description) => {
71				Self::TableColumnDescription(table_column_description.clone())
72			}
73			Property::TableColumnHeader(table_column_header) => {
74				Self::TableColumnHeader(table_column_header.clone())
75			}
76			Property::TableRowDescription(table_row_description) => {
77				Self::TableRowDescription(table_row_description.clone())
78			}
79			Property::TableRowHeader(table_row_header) => {
80				Self::TableRowHeader(table_row_header.clone())
81			}
82			Property::TableSummary(table_summary) => Self::TableSummary(table_summary.clone()),
83			Property::Other((property, value)) => Self::Other((
84				property.clone(),
85				value
86					.try_clone()
87					.expect("Could not clone 'value'.  Since properties are not known to carry files, we do not expect to exceed open file limit."),
88			)),
89		}
90	}
91}
92
93impl Default for Property {
94	fn default() -> Self {
95		Self::Other((String::default(), u64::default().into()))
96	}
97}
98
99impl TryFrom<EventBodyOwned> for Property {
100	type Error = AtspiError;
101
102	fn try_from(body: EventBodyOwned) -> Result<Self, Self::Error> {
103		let property = body.kind;
104
105		match property.as_str() {
106			"accessible-name" => Ok(Self::Name(
107				body.any_data
108					.try_into()
109					.map_err(|_| AtspiError::ParseError("accessible-name"))?,
110			)),
111			"accessible-description" => Ok(Self::Description(
112				body.any_data
113					.try_into()
114					.map_err(|_| AtspiError::ParseError("accessible-description"))?,
115			)),
116			"accessible-role" => Ok(Self::Role({
117				let role_int: u32 = body
118					.any_data
119					.try_into()
120					.map_err(|_| AtspiError::ParseError("accessible-role"))?;
121				let role: crate::Role = crate::Role::try_from(role_int)
122					.map_err(|_| AtspiError::ParseError("accessible-role"))?;
123				role
124			})),
125			"accessible-parent" => Ok(Self::Parent(
126				body.any_data
127					.try_into()
128					.map_err(|_| AtspiError::ParseError("accessible-parent"))?,
129			)),
130			"accessible-table-caption" => Ok(Self::TableCaption(
131				body.any_data
132					.try_into()
133					.map_err(|_| AtspiError::ParseError("accessible-table-caption"))?,
134			)),
135			"table-column-description" => Ok(Self::TableColumnDescription(
136				body.any_data
137					.try_into()
138					.map_err(|_| AtspiError::ParseError("table-column-description"))?,
139			)),
140			"table-column-header" => Ok(Self::TableColumnHeader(
141				body.any_data
142					.try_into()
143					.map_err(|_| AtspiError::ParseError("table-column-header"))?,
144			)),
145			"table-row-description" => Ok(Self::TableRowDescription(
146				body.any_data
147					.try_into()
148					.map_err(|_| AtspiError::ParseError("table-row-description"))?,
149			)),
150			"table-row-header" => Ok(Self::TableRowHeader(
151				body.any_data
152					.try_into()
153					.map_err(|_| AtspiError::ParseError("table-row-header"))?,
154			)),
155			"table-summary" => Ok(Self::TableSummary(
156				body.any_data
157					.try_into()
158					.map_err(|_| AtspiError::ParseError("table-summary"))?,
159			)),
160			_ => Ok(Self::Other((property, body.any_data))),
161		}
162	}
163}
164
165impl From<Property> for OwnedValue {
166	fn from(property: Property) -> Self {
167		let value = match property {
168			Property::Name(name) => Value::from(name),
169			Property::Description(description) => Value::from(description),
170			Property::Role(role) => Value::from(role as u32),
171			Property::Parent(parent) => Value::from(parent),
172			Property::TableCaption(table_caption) => Value::from(table_caption),
173			Property::TableColumnDescription(table_column_description) => {
174				Value::from(table_column_description)
175			}
176			Property::TableColumnHeader(table_column_header) => Value::from(table_column_header),
177			Property::TableRowDescription(table_row_description) => {
178				Value::from(table_row_description)
179			}
180			Property::TableRowHeader(table_row_header) => Value::from(table_row_header),
181			Property::TableSummary(table_summary) => Value::from(table_summary),
182			Property::Other((_, value)) => value.into(),
183		};
184		value.try_into().expect("Should succeed as there are no borrowed file descriptors involved that could, potentially, exceed the open file limit when converted to OwnedValue")
185	}
186}
187
188#[derive(Debug, PartialEq, Clone, serde::Serialize, serde::Deserialize, Eq, Hash, Default)]
189pub struct BoundsChangedEvent {
190	/// The [`crate::ObjectRef`] which the event applies to.
191	pub item: crate::events::ObjectRef,
192}
193
194#[derive(Debug, PartialEq, Clone, serde::Serialize, serde::Deserialize, Eq, Hash, Default)]
195pub struct LinkSelectedEvent {
196	/// The [`crate::ObjectRef`] which the event applies to.
197	pub item: crate::events::ObjectRef,
198}
199
200/// A state of an object has been modified.
201/// A [`State`] can be added or removed from any [`crate::ObjectRef`].
202#[derive(Debug, PartialEq, Clone, serde::Serialize, serde::Deserialize, Eq, Hash, Default)]
203pub struct StateChangedEvent {
204	/// The [`crate::ObjectRef`] which the event applies to.
205	pub item: crate::events::ObjectRef,
206	/// The state to be enabled/disabled.
207	pub state: State,
208	/// Whether the state was enabled or disabled.
209	#[serde(with = "i32_bool_conversion")]
210	pub enabled: bool,
211}
212
213mod i32_bool_conversion {
214	use serde::{Deserialize, Deserializer, Serializer};
215	/// Convert an integer flag to a boolean.
216	/// returns true if value is more than 0, otherwise false
217	pub fn deserialize<'de, D>(de: D) -> Result<bool, D::Error>
218	where
219		D: Deserializer<'de>,
220	{
221		let int: i32 = Deserialize::deserialize(de)?;
222		Ok(int > 0)
223	}
224
225	/// Convert a boolean flag to an integer.
226	/// returns 0 if false and 1 if true
227	#[allow(clippy::trivially_copy_pass_by_ref)]
228	pub fn serialize<S>(b: &bool, ser: S) -> Result<S::Ok, S::Error>
229	where
230		S: Serializer,
231	{
232		let val: i32 = (*b).into();
233		ser.serialize_i32(val)
234	}
235}
236
237/// A child of an [`crate::ObjectRef`] has been added or removed.
238#[derive(Debug, PartialEq, Clone, serde::Serialize, serde::Deserialize, Eq, Hash, Default)]
239pub struct ChildrenChangedEvent {
240	/// The [`crate::ObjectRef`] which the event applies to.
241	pub item: crate::events::ObjectRef,
242	/// The [`crate::Operation`] being performed.
243	pub operation: crate::Operation,
244	/// Index to remove from/add to.
245	pub index_in_parent: i32,
246	/// A reference to the new child.
247	pub child: ObjectRef,
248}
249
250#[derive(Debug, PartialEq, Clone, serde::Serialize, serde::Deserialize, Eq, Hash, Default)]
251pub struct VisibleDataChangedEvent {
252	/// The [`crate::ObjectRef`] which the event applies to.
253	pub item: crate::events::ObjectRef,
254}
255
256#[derive(Debug, PartialEq, Clone, serde::Serialize, serde::Deserialize, Eq, Hash, Default)]
257pub struct SelectionChangedEvent {
258	/// The [`crate::ObjectRef`] which the event applies to.
259	pub item: crate::events::ObjectRef,
260}
261
262#[derive(Debug, PartialEq, Clone, serde::Serialize, serde::Deserialize, Eq, Hash, Default)]
263pub struct ModelChangedEvent {
264	/// The [`crate::ObjectRef`] which the event applies to.
265	pub item: crate::events::ObjectRef,
266}
267
268#[derive(Debug, PartialEq, Clone, serde::Serialize, serde::Deserialize, Eq, Hash, Default)]
269pub struct ActiveDescendantChangedEvent {
270	/// The [`crate::ObjectRef`] which the event applies to.
271	pub item: crate::events::ObjectRef,
272	pub child: ObjectRef,
273}
274
275#[derive(Debug, PartialEq, Clone, serde::Serialize, serde::Deserialize, Eq, Hash, Default)]
276pub struct AnnouncementEvent {
277	/// The [`crate::ObjectRef`] which the event applies to.
278	pub item: crate::events::ObjectRef,
279	/// Text of the announcement.
280	pub text: String,
281	/// Politeness level.
282	pub live: crate::Politeness,
283}
284
285#[derive(Debug, PartialEq, Clone, serde::Serialize, serde::Deserialize, Eq, Hash, Default)]
286pub struct AttributesChangedEvent {
287	/// The [`crate::ObjectRef`] which the event applies to.
288	pub item: crate::events::ObjectRef,
289}
290
291/// A row has been added to a table.
292#[derive(Debug, PartialEq, Clone, serde::Serialize, serde::Deserialize, Eq, Hash, Default)]
293pub struct RowInsertedEvent {
294	/// The table which has had a row inserted.
295	pub item: crate::events::ObjectRef,
296}
297
298/// A row has been moved within a table.
299#[derive(Debug, PartialEq, Clone, serde::Serialize, serde::Deserialize, Eq, Hash, Default)]
300pub struct RowReorderedEvent {
301	/// The table which has had a row re-ordered.
302	pub item: crate::events::ObjectRef,
303}
304
305/// A row has been deleted from a table.
306#[derive(Debug, PartialEq, Clone, serde::Serialize, serde::Deserialize, Eq, Hash, Default)]
307pub struct RowDeletedEvent {
308	/// The table which has had a row removed.
309	pub item: crate::events::ObjectRef,
310}
311
312/// A column has been added to a table.
313#[derive(Debug, PartialEq, Clone, serde::Serialize, serde::Deserialize, Eq, Hash, Default)]
314pub struct ColumnInsertedEvent {
315	/// The table which has had a column inserted.
316	pub item: crate::events::ObjectRef,
317}
318
319/// A column has been re-ordered within a table.
320#[derive(Debug, PartialEq, Clone, serde::Serialize, serde::Deserialize, Eq, Hash, Default)]
321pub struct ColumnReorderedEvent {
322	/// The table which has had a column re-ordered.
323	pub item: crate::events::ObjectRef,
324}
325
326/// A column has been removed from a table.
327#[derive(Debug, PartialEq, Clone, serde::Serialize, serde::Deserialize, Eq, Hash, Default)]
328pub struct ColumnDeletedEvent {
329	/// The table which has had a column removed.
330	pub item: crate::events::ObjectRef,
331}
332
333#[derive(Debug, PartialEq, Clone, serde::Serialize, serde::Deserialize, Eq, Hash, Default)]
334pub struct TextBoundsChangedEvent {
335	/// The [`crate::ObjectRef`] which the event applies to.
336	pub item: crate::events::ObjectRef,
337}
338
339#[derive(Debug, PartialEq, Clone, serde::Serialize, serde::Deserialize, Eq, Hash, Default)]
340pub struct TextSelectionChangedEvent {
341	/// The [`crate::ObjectRef`] which the event applies to.
342	pub item: crate::events::ObjectRef,
343}
344
345/// Text has changed within an [`crate::ObjectRef`].
346#[derive(Debug, PartialEq, Clone, serde::Serialize, serde::Deserialize, Eq, Hash, Default)]
347pub struct TextChangedEvent {
348	/// The [`crate::ObjectRef`] which the event applies to.
349	pub item: crate::events::ObjectRef,
350	/// The [`crate::Operation`] being performed.
351	pub operation: crate::Operation,
352	/// starting index of the insertion/deletion
353	pub start_pos: i32,
354	/// length of the insertion/deletion
355	pub length: i32,
356	/// the text being inserted/deleted
357	pub text: String,
358}
359
360/// Signal that some attributes about the text (usually styling) have changed.
361/// This event does not encode _what_ has changed about the attributes, merely that they have
362/// changed.
363#[derive(Debug, PartialEq, Clone, serde::Serialize, serde::Deserialize, Eq, Hash, Default)]
364pub struct TextAttributesChangedEvent {
365	/// The [`crate::ObjectRef`] which the event applies to.
366	pub item: crate::events::ObjectRef,
367}
368
369/// The caret of the user also known as a cursor (not to be confused with mouse pointer) has changed position.
370#[derive(Debug, PartialEq, Clone, serde::Serialize, serde::Deserialize, Eq, Hash, Default)]
371pub struct TextCaretMovedEvent {
372	/// The object on which the caret has been moved on.
373	pub item: crate::events::ObjectRef,
374	/// New position of the caret.
375	pub position: i32,
376}
377
378impl BusProperties for PropertyChangeEvent {
379	const DBUS_MEMBER: &'static str = "PropertyChange";
380	const DBUS_INTERFACE: &'static str = "org.a11y.atspi.Event.Object";
381	const MATCH_RULE_STRING: &'static str =
382		"type='signal',interface='org.a11y.atspi.Event.Object',member='PropertyChange'";
383	const REGISTRY_EVENT_STRING: &'static str = "Object:";
384}
385
386#[cfg(feature = "zbus")]
387impl MessageConversion for PropertyChangeEvent {
388	type Body = EventBodyOwned;
389
390	fn from_message_unchecked_parts(item: ObjectRef, body: Self::Body) -> Result<Self, AtspiError> {
391		let property = body.kind.to_string();
392		let value: Property = body.try_into()?;
393		Ok(Self { item, property, value })
394	}
395	fn from_message_unchecked(msg: &zbus::Message) -> Result<Self, AtspiError> {
396		let item = msg.try_into()?;
397		// TODO: Check the likely thing first _and_ body.deserialize already checks the signature
398		let body = if msg.body().signature() == crate::events::QSPI_EVENT_SIGNATURE {
399			msg.body().deserialize::<crate::events::EventBodyQtOwned>()?.into()
400		} else {
401			msg.body().deserialize()?
402		};
403		Self::from_message_unchecked_parts(item, body)
404	}
405	fn body(&self) -> Self::Body {
406		let copy = self.clone();
407		copy.into()
408	}
409}
410
411impl BusProperties for BoundsChangedEvent {
412	const DBUS_MEMBER: &'static str = "BoundsChanged";
413	const DBUS_INTERFACE: &'static str = "org.a11y.atspi.Event.Object";
414	const MATCH_RULE_STRING: &'static str =
415		"type='signal',interface='org.a11y.atspi.Event.Object',member='BoundsChanged'";
416	const REGISTRY_EVENT_STRING: &'static str = "Object:";
417}
418
419impl BusProperties for LinkSelectedEvent {
420	const DBUS_MEMBER: &'static str = "LinkSelected";
421	const DBUS_INTERFACE: &'static str = "org.a11y.atspi.Event.Object";
422	const MATCH_RULE_STRING: &'static str =
423		"type='signal',interface='org.a11y.atspi.Event.Object',member='LinkSelected'";
424	const REGISTRY_EVENT_STRING: &'static str = "Object:";
425}
426
427impl BusProperties for StateChangedEvent {
428	const DBUS_MEMBER: &'static str = "StateChanged";
429	const DBUS_INTERFACE: &'static str = "org.a11y.atspi.Event.Object";
430	const MATCH_RULE_STRING: &'static str =
431		"type='signal',interface='org.a11y.atspi.Event.Object',member='StateChanged'";
432	const REGISTRY_EVENT_STRING: &'static str = "Object:";
433}
434
435#[cfg(feature = "zbus")]
436impl MessageConversion for StateChangedEvent {
437	type Body = EventBodyOwned;
438
439	fn from_message_unchecked_parts(item: ObjectRef, body: Self::Body) -> Result<Self, AtspiError> {
440		Ok(Self { item, state: body.kind.into(), enabled: body.detail1 > 0 })
441	}
442	fn from_message_unchecked(msg: &zbus::Message) -> Result<Self, AtspiError> {
443		let item = msg.try_into()?;
444		// TODO: Check the likely thing first _and_ body.deserialize already checks the signature
445		let body = if msg.body().signature() == crate::events::QSPI_EVENT_SIGNATURE {
446			msg.body().deserialize::<crate::events::EventBodyQtOwned>()?.into()
447		} else {
448			msg.body().deserialize()?
449		};
450		Self::from_message_unchecked_parts(item, body)
451	}
452	fn body(&self) -> Self::Body {
453		let copy = self.clone();
454		copy.into()
455	}
456}
457
458impl BusProperties for ChildrenChangedEvent {
459	const DBUS_MEMBER: &'static str = "ChildrenChanged";
460	const DBUS_INTERFACE: &'static str = "org.a11y.atspi.Event.Object";
461	const MATCH_RULE_STRING: &'static str =
462		"type='signal',interface='org.a11y.atspi.Event.Object',member='ChildrenChanged'";
463	const REGISTRY_EVENT_STRING: &'static str = "Object:";
464}
465
466#[cfg(feature = "zbus")]
467impl MessageConversion for ChildrenChangedEvent {
468	type Body = EventBodyOwned;
469
470	fn from_message_unchecked_parts(item: ObjectRef, body: Self::Body) -> Result<Self, AtspiError> {
471		Ok(Self {
472			item,
473			operation: body.kind.as_str().parse()?,
474			index_in_parent: body.detail1,
475			child: body.any_data.try_into()?,
476		})
477	}
478	fn from_message_unchecked(msg: &zbus::Message) -> Result<Self, AtspiError> {
479		let item = msg.try_into()?;
480		let body = if msg.body().signature() == crate::events::QSPI_EVENT_SIGNATURE {
481			msg.body().deserialize::<crate::events::EventBodyQtOwned>()?.into()
482		} else {
483			msg.body().deserialize()?
484		};
485		Self::from_message_unchecked_parts(item, body)
486	}
487	fn body(&self) -> Self::Body {
488		let copy = self.clone();
489		copy.into()
490	}
491}
492
493impl BusProperties for VisibleDataChangedEvent {
494	const DBUS_MEMBER: &'static str = "VisibleDataChanged";
495	const DBUS_INTERFACE: &'static str = "org.a11y.atspi.Event.Object";
496	const MATCH_RULE_STRING: &'static str =
497		"type='signal',interface='org.a11y.atspi.Event.Object',member='VisibleDataChanged'";
498	const REGISTRY_EVENT_STRING: &'static str = "Object:";
499}
500
501impl BusProperties for SelectionChangedEvent {
502	const DBUS_MEMBER: &'static str = "SelectionChanged";
503	const DBUS_INTERFACE: &'static str = "org.a11y.atspi.Event.Object";
504	const MATCH_RULE_STRING: &'static str =
505		"type='signal',interface='org.a11y.atspi.Event.Object',member='SelectionChanged'";
506	const REGISTRY_EVENT_STRING: &'static str = "Object:";
507}
508
509impl BusProperties for ModelChangedEvent {
510	const DBUS_MEMBER: &'static str = "ModelChanged";
511	const DBUS_INTERFACE: &'static str = "org.a11y.atspi.Event.Object";
512	const MATCH_RULE_STRING: &'static str =
513		"type='signal',interface='org.a11y.atspi.Event.Object',member='ModelChanged'";
514	const REGISTRY_EVENT_STRING: &'static str = "Object:";
515}
516
517impl BusProperties for ActiveDescendantChangedEvent {
518	const DBUS_MEMBER: &'static str = "ActiveDescendantChanged";
519	const DBUS_INTERFACE: &'static str = "org.a11y.atspi.Event.Object";
520	const MATCH_RULE_STRING: &'static str =
521		"type='signal',interface='org.a11y.atspi.Event.Object',member='ActiveDescendantChanged'";
522	const REGISTRY_EVENT_STRING: &'static str = "Object:";
523}
524
525#[cfg(feature = "zbus")]
526impl MessageConversion for ActiveDescendantChangedEvent {
527	type Body = EventBodyOwned;
528
529	fn from_message_unchecked_parts(item: ObjectRef, body: Self::Body) -> Result<Self, AtspiError> {
530		Ok(Self { item, child: body.any_data.try_into()? })
531	}
532	fn from_message_unchecked(msg: &zbus::Message) -> Result<Self, AtspiError> {
533		let item = msg.try_into()?;
534		// TODO: Check the likely thing first _and_ body.deserialize already checks the signature
535		let body = if msg.body().signature() == crate::events::QSPI_EVENT_SIGNATURE {
536			msg.body().deserialize::<crate::events::EventBodyQtOwned>()?.into()
537		} else {
538			msg.body().deserialize()?
539		};
540		Self::from_message_unchecked_parts(item, body)
541	}
542	fn body(&self) -> Self::Body {
543		let copy = self.clone();
544		copy.into()
545	}
546}
547
548impl BusProperties for AnnouncementEvent {
549	const DBUS_MEMBER: &'static str = "Announcement";
550	const DBUS_INTERFACE: &'static str = "org.a11y.atspi.Event.Object";
551	const MATCH_RULE_STRING: &'static str =
552		"type='signal',interface='org.a11y.atspi.Event.Object',member='Announcement'";
553	const REGISTRY_EVENT_STRING: &'static str = "Object:";
554}
555
556#[cfg(feature = "zbus")]
557impl MessageConversion for AnnouncementEvent {
558	type Body = EventBodyOwned;
559
560	fn from_message_unchecked_parts(item: ObjectRef, body: Self::Body) -> Result<Self, AtspiError> {
561		Ok(Self {
562			item,
563			text: body.any_data.try_into().map_err(|_| AtspiError::Conversion("text"))?,
564			live: body.detail1.try_into()?,
565		})
566	}
567	fn from_message_unchecked(msg: &zbus::Message) -> Result<Self, AtspiError> {
568		let item = msg.try_into()?;
569		// TODO: Check the likely thing first _and_ body.deserialize already checks the signature
570		let body = if msg.body().signature() == crate::events::QSPI_EVENT_SIGNATURE {
571			msg.body().deserialize::<crate::events::EventBodyQtOwned>()?.into()
572		} else {
573			msg.body().deserialize()?
574		};
575		Self::from_message_unchecked_parts(item, body)
576	}
577	fn body(&self) -> Self::Body {
578		let copy = self.clone();
579		copy.into()
580	}
581}
582
583impl BusProperties for AttributesChangedEvent {
584	const DBUS_MEMBER: &'static str = "AttributesChanged";
585	const DBUS_INTERFACE: &'static str = "org.a11y.atspi.Event.Object";
586	const MATCH_RULE_STRING: &'static str =
587		"type='signal',interface='org.a11y.atspi.Event.Object',member='AttributesChanged'";
588	const REGISTRY_EVENT_STRING: &'static str = "Object:";
589}
590
591impl BusProperties for RowInsertedEvent {
592	const DBUS_MEMBER: &'static str = "RowInserted";
593	const DBUS_INTERFACE: &'static str = "org.a11y.atspi.Event.Object";
594	const MATCH_RULE_STRING: &'static str =
595		"type='signal',interface='org.a11y.atspi.Event.Object',member='RowInserted'";
596	const REGISTRY_EVENT_STRING: &'static str = "Object:";
597}
598
599impl BusProperties for RowReorderedEvent {
600	const DBUS_MEMBER: &'static str = "RowReordered";
601	const DBUS_INTERFACE: &'static str = "org.a11y.atspi.Event.Object";
602	const MATCH_RULE_STRING: &'static str =
603		"type='signal',interface='org.a11y.atspi.Event.Object',member='RowReordered'";
604	const REGISTRY_EVENT_STRING: &'static str = "Object:";
605}
606
607impl BusProperties for RowDeletedEvent {
608	const DBUS_MEMBER: &'static str = "RowDeleted";
609	const DBUS_INTERFACE: &'static str = "org.a11y.atspi.Event.Object";
610	const MATCH_RULE_STRING: &'static str =
611		"type='signal',interface='org.a11y.atspi.Event.Object',member='RowDeleted'";
612	const REGISTRY_EVENT_STRING: &'static str = "Object:";
613}
614
615impl BusProperties for ColumnInsertedEvent {
616	const DBUS_MEMBER: &'static str = "ColumnInserted";
617	const DBUS_INTERFACE: &'static str = "org.a11y.atspi.Event.Object";
618	const MATCH_RULE_STRING: &'static str =
619		"type='signal',interface='org.a11y.atspi.Event.Object',member='ColumnInserted'";
620	const REGISTRY_EVENT_STRING: &'static str = "Object:";
621}
622
623impl BusProperties for ColumnReorderedEvent {
624	const DBUS_MEMBER: &'static str = "ColumnReordered";
625	const DBUS_INTERFACE: &'static str = "org.a11y.atspi.Event.Object";
626	const MATCH_RULE_STRING: &'static str =
627		"type='signal',interface='org.a11y.atspi.Event.Object',member='ColumnReordered'";
628	const REGISTRY_EVENT_STRING: &'static str = "Object:";
629}
630
631impl BusProperties for ColumnDeletedEvent {
632	const DBUS_MEMBER: &'static str = "ColumnDeleted";
633	const DBUS_INTERFACE: &'static str = "org.a11y.atspi.Event.Object";
634	const MATCH_RULE_STRING: &'static str =
635		"type='signal',interface='org.a11y.atspi.Event.Object',member='ColumnDeleted'";
636	const REGISTRY_EVENT_STRING: &'static str = "Object:";
637}
638
639impl BusProperties for TextBoundsChangedEvent {
640	const DBUS_MEMBER: &'static str = "TextBoundsChanged";
641	const DBUS_INTERFACE: &'static str = "org.a11y.atspi.Event.Object";
642	const MATCH_RULE_STRING: &'static str =
643		"type='signal',interface='org.a11y.atspi.Event.Object',member='TextBoundsChanged'";
644	const REGISTRY_EVENT_STRING: &'static str = "Object:";
645}
646
647impl BusProperties for TextSelectionChangedEvent {
648	const DBUS_MEMBER: &'static str = "TextSelectionChanged";
649	const DBUS_INTERFACE: &'static str = "org.a11y.atspi.Event.Object";
650	const MATCH_RULE_STRING: &'static str =
651		"type='signal',interface='org.a11y.atspi.Event.Object',member='TextSelectionChanged'";
652	const REGISTRY_EVENT_STRING: &'static str = "Object:";
653}
654
655impl BusProperties for TextChangedEvent {
656	const DBUS_MEMBER: &'static str = "TextChanged";
657	const DBUS_INTERFACE: &'static str = "org.a11y.atspi.Event.Object";
658	const MATCH_RULE_STRING: &'static str =
659		"type='signal',interface='org.a11y.atspi.Event.Object',member='TextChanged'";
660	const REGISTRY_EVENT_STRING: &'static str = "Object:";
661}
662
663#[cfg(feature = "zbus")]
664impl MessageConversion for TextChangedEvent {
665	type Body = EventBodyOwned;
666
667	fn from_message_unchecked_parts(item: ObjectRef, body: Self::Body) -> Result<Self, AtspiError> {
668		Ok(Self {
669			item,
670			operation: body.kind.as_str().parse()?,
671			start_pos: body.detail1,
672			length: body.detail2,
673			text: body.any_data.try_into()?,
674		})
675	}
676	fn from_message_unchecked(msg: &zbus::Message) -> Result<Self, AtspiError> {
677		let item = msg.try_into()?;
678		// TODO: Check the likely thing first _and_ body.deserialize already checks the signature
679		let body = if msg.body().signature() == crate::events::QSPI_EVENT_SIGNATURE {
680			msg.body().deserialize::<EventBodyQtOwned>()?.into()
681		} else {
682			msg.body().deserialize()?
683		};
684		Self::from_message_unchecked_parts(item, body)
685	}
686	fn body(&self) -> Self::Body {
687		let copy = self.clone();
688		copy.into()
689	}
690}
691
692impl BusProperties for TextAttributesChangedEvent {
693	const DBUS_MEMBER: &'static str = "TextAttributesChanged";
694	const DBUS_INTERFACE: &'static str = "org.a11y.atspi.Event.Object";
695	const MATCH_RULE_STRING: &'static str =
696		"type='signal',interface='org.a11y.atspi.Event.Object',member='TextAttributesChanged'";
697	const REGISTRY_EVENT_STRING: &'static str = "Object:";
698}
699
700impl BusProperties for TextCaretMovedEvent {
701	const DBUS_MEMBER: &'static str = "TextCaretMoved";
702	const DBUS_INTERFACE: &'static str = "org.a11y.atspi.Event.Object";
703	const MATCH_RULE_STRING: &'static str =
704		"type='signal',interface='org.a11y.atspi.Event.Object',member='TextCaretMoved'";
705	const REGISTRY_EVENT_STRING: &'static str = "Object:";
706}
707
708#[cfg(feature = "zbus")]
709impl MessageConversion for TextCaretMovedEvent {
710	type Body = EventBodyOwned;
711
712	fn from_message_unchecked_parts(item: ObjectRef, body: Self::Body) -> Result<Self, AtspiError> {
713		Ok(Self { item, position: body.detail1 })
714	}
715	fn from_message_unchecked(msg: &zbus::Message) -> Result<Self, AtspiError> {
716		let item = msg.try_into()?;
717		// TODO: Check the likely thing first _and_ body.deserialize already checks the signature
718		let body = if msg.body().signature() == crate::events::QSPI_EVENT_SIGNATURE {
719			msg.body().deserialize::<EventBodyQtOwned>()?.into()
720		} else {
721			msg.body().deserialize()?
722		};
723		Self::from_message_unchecked_parts(item, body)
724	}
725	fn body(&self) -> Self::Body {
726		let copy = self.clone();
727		copy.into()
728	}
729}
730
731event_test_cases!(PropertyChangeEvent);
732impl_to_dbus_message!(PropertyChangeEvent);
733impl_from_dbus_message!(PropertyChangeEvent);
734impl_event_properties!(PropertyChangeEvent);
735
736impl From<PropertyChangeEvent> for EventBodyOwned {
737	fn from(event: PropertyChangeEvent) -> Self {
738		EventBodyOwned { kind: event.property, any_data: event.value.into(), ..Default::default() }
739	}
740}
741
742event_test_cases!(BoundsChangedEvent);
743impl_to_dbus_message!(BoundsChangedEvent);
744impl_from_dbus_message!(BoundsChangedEvent);
745impl_event_properties!(BoundsChangedEvent);
746impl_from_object_ref!(BoundsChangedEvent);
747
748event_test_cases!(LinkSelectedEvent);
749impl_to_dbus_message!(LinkSelectedEvent);
750impl_from_dbus_message!(LinkSelectedEvent);
751impl_event_properties!(LinkSelectedEvent);
752impl_from_object_ref!(LinkSelectedEvent);
753
754event_test_cases!(StateChangedEvent);
755impl_to_dbus_message!(StateChangedEvent);
756impl_from_dbus_message!(StateChangedEvent);
757impl_event_properties!(StateChangedEvent);
758impl From<StateChangedEvent> for EventBodyOwned {
759	fn from(event: StateChangedEvent) -> Self {
760		EventBodyOwned {
761			kind: event.state.to_string(),
762			detail1: event.enabled.into(),
763			..Default::default()
764		}
765	}
766}
767
768event_test_cases!(ChildrenChangedEvent);
769impl_to_dbus_message!(ChildrenChangedEvent);
770impl_from_dbus_message!(ChildrenChangedEvent);
771impl_event_properties!(ChildrenChangedEvent);
772impl From<ChildrenChangedEvent> for EventBodyOwned {
773	fn from(event: ChildrenChangedEvent) -> Self {
774		EventBodyOwned {
775			kind: event.operation.to_string(),
776			detail1: event.index_in_parent,
777
778			// `OwnedValue` is constructed from the `crate::ObjectRef`
779			// Only path to fail is to convert a Fd into an `OwnedValue`.
780			// Therefore, this is safe.
781			any_data: Value::from(event.child)
782				.try_into()
783				.expect("Failed to convert child to OwnedValue"),
784			..Default::default()
785		}
786	}
787}
788
789event_test_cases!(VisibleDataChangedEvent);
790impl_to_dbus_message!(VisibleDataChangedEvent);
791impl_from_dbus_message!(VisibleDataChangedEvent);
792impl_event_properties!(VisibleDataChangedEvent);
793impl_from_object_ref!(VisibleDataChangedEvent);
794
795event_test_cases!(SelectionChangedEvent);
796impl_to_dbus_message!(SelectionChangedEvent);
797impl_from_dbus_message!(SelectionChangedEvent);
798impl_event_properties!(SelectionChangedEvent);
799impl_from_object_ref!(SelectionChangedEvent);
800
801event_test_cases!(ModelChangedEvent);
802impl_to_dbus_message!(ModelChangedEvent);
803impl_from_dbus_message!(ModelChangedEvent);
804impl_event_properties!(ModelChangedEvent);
805impl_from_object_ref!(ModelChangedEvent);
806
807event_test_cases!(ActiveDescendantChangedEvent);
808impl_to_dbus_message!(ActiveDescendantChangedEvent);
809impl_from_dbus_message!(ActiveDescendantChangedEvent);
810impl_event_properties!(ActiveDescendantChangedEvent);
811impl From<ActiveDescendantChangedEvent> for EventBodyOwned {
812	fn from(event: ActiveDescendantChangedEvent) -> Self {
813		EventBodyOwned {
814			// `OwnedValue` is constructed from the `crate::ObjectRef`
815			// Only path to fail is to convert a Fd into an `OwnedValue`.
816			// Therefore, this is safe.
817			any_data: Value::from(event.child)
818				.try_to_owned()
819				.expect("Failed to convert child to OwnedValue"),
820			..Default::default()
821		}
822	}
823}
824
825event_test_cases!(AnnouncementEvent);
826impl_to_dbus_message!(AnnouncementEvent);
827impl_from_dbus_message!(AnnouncementEvent);
828impl_event_properties!(AnnouncementEvent);
829impl From<AnnouncementEvent> for EventBodyOwned {
830	fn from(event: AnnouncementEvent) -> Self {
831		EventBodyOwned {
832			detail1: event.live as i32,
833			// `OwnedValue` is constructed from `String`
834			// Therefore, this is safe.
835			any_data: Value::from(event.text)
836				.try_to_owned()
837				.expect("Failed to convert text to OwnedValue"),
838			..Default::default()
839		}
840	}
841}
842
843event_test_cases!(AttributesChangedEvent);
844impl_to_dbus_message!(AttributesChangedEvent);
845impl_from_dbus_message!(AttributesChangedEvent);
846impl_event_properties!(AttributesChangedEvent);
847impl_from_object_ref!(AttributesChangedEvent);
848
849event_test_cases!(RowInsertedEvent);
850impl_to_dbus_message!(RowInsertedEvent);
851impl_from_dbus_message!(RowInsertedEvent);
852impl_event_properties!(RowInsertedEvent);
853impl_from_object_ref!(RowInsertedEvent);
854
855event_test_cases!(RowReorderedEvent);
856impl_to_dbus_message!(RowReorderedEvent);
857impl_from_dbus_message!(RowReorderedEvent);
858impl_event_properties!(RowReorderedEvent);
859impl_from_object_ref!(RowReorderedEvent);
860
861event_test_cases!(RowDeletedEvent);
862impl_to_dbus_message!(RowDeletedEvent);
863impl_from_dbus_message!(RowDeletedEvent);
864impl_event_properties!(RowDeletedEvent);
865impl_from_object_ref!(RowDeletedEvent);
866
867event_test_cases!(ColumnInsertedEvent);
868impl_to_dbus_message!(ColumnInsertedEvent);
869impl_from_dbus_message!(ColumnInsertedEvent);
870impl_event_properties!(ColumnInsertedEvent);
871impl_from_object_ref!(ColumnInsertedEvent);
872
873event_test_cases!(ColumnReorderedEvent);
874impl_to_dbus_message!(ColumnReorderedEvent);
875impl_from_dbus_message!(ColumnReorderedEvent);
876impl_event_properties!(ColumnReorderedEvent);
877impl_from_object_ref!(ColumnReorderedEvent);
878
879event_test_cases!(ColumnDeletedEvent);
880impl_to_dbus_message!(ColumnDeletedEvent);
881impl_from_dbus_message!(ColumnDeletedEvent);
882impl_event_properties!(ColumnDeletedEvent);
883impl_from_object_ref!(ColumnDeletedEvent);
884
885event_test_cases!(TextBoundsChangedEvent);
886impl_to_dbus_message!(TextBoundsChangedEvent);
887impl_from_dbus_message!(TextBoundsChangedEvent);
888impl_event_properties!(TextBoundsChangedEvent);
889impl_from_object_ref!(TextBoundsChangedEvent);
890
891event_test_cases!(TextSelectionChangedEvent);
892impl_to_dbus_message!(TextSelectionChangedEvent);
893impl_from_dbus_message!(TextSelectionChangedEvent);
894impl_event_properties!(TextSelectionChangedEvent);
895impl_from_object_ref!(TextSelectionChangedEvent);
896
897event_test_cases!(TextChangedEvent);
898impl_to_dbus_message!(TextChangedEvent);
899impl_from_dbus_message!(TextChangedEvent);
900impl_event_properties!(TextChangedEvent);
901impl From<TextChangedEvent> for EventBodyOwned {
902	fn from(event: TextChangedEvent) -> Self {
903		EventBodyOwned {
904			kind: event.operation.to_string(),
905			detail1: event.start_pos,
906			detail2: event.length,
907
908			// `OwnedValue` is constructed from a `String`
909			// Therefore, this is safe.
910			any_data: Value::from(event.text)
911				.try_to_owned()
912				.expect("Failed to convert child to OwnedValue"),
913			properties: Properties,
914		}
915	}
916}
917
918event_test_cases!(TextAttributesChangedEvent);
919impl_to_dbus_message!(TextAttributesChangedEvent);
920impl_from_dbus_message!(TextAttributesChangedEvent);
921impl_event_properties!(TextAttributesChangedEvent);
922impl_from_object_ref!(TextAttributesChangedEvent);
923
924event_test_cases!(TextCaretMovedEvent);
925impl_to_dbus_message!(TextCaretMovedEvent);
926impl_from_dbus_message!(TextCaretMovedEvent);
927impl_event_properties!(TextCaretMovedEvent);
928impl From<TextCaretMovedEvent> for EventBodyOwned {
929	fn from(event: TextCaretMovedEvent) -> Self {
930		EventBodyOwned { detail1: event.position, ..Default::default() }
931	}
932}