//! Accessibility for Bevy #![warn(missing_docs)] #![allow(clippy::type_complexity)] #![forbid(unsafe_code)] use std::{ num::NonZeroU128, sync::{atomic::AtomicBool, Arc}, }; pub use accesskit; use accesskit::{NodeBuilder, NodeId}; use bevy_app::Plugin; use bevy_derive::{Deref, DerefMut}; use bevy_ecs::{ prelude::{Component, Entity, Event}, system::Resource, }; /// Wrapper struct for [`accesskit::ActionRequest`]. Required to allow it to be used as an `Event`. #[derive(Event, Deref, DerefMut)] pub struct ActionRequest(pub accesskit::ActionRequest); /// Resource that tracks whether an assistive technology has requested /// accessibility information. /// /// Useful if a third-party plugin needs to conditionally integrate with /// `AccessKit` #[derive(Resource, Default, Clone, Debug, Deref, DerefMut)] pub struct AccessibilityRequested(Arc); /// Component to wrap a [`accesskit::Node`], representing this entity to the platform's /// accessibility API. /// /// If an entity has a parent, and that parent also has an `AccessibilityNode`, /// the entity's node will be a child of the parent's node. /// /// If the entity doesn't have a parent, or if the immediate parent doesn't have /// an `AccessibilityNode`, its node will be an immediate child of the primary window. #[derive(Component, Clone, Deref, DerefMut)] pub struct AccessibilityNode(pub NodeBuilder); impl From for AccessibilityNode { fn from(node: NodeBuilder) -> Self { Self(node) } } /// Extensions to ease integrating entities with [`AccessKit`](https://accesskit.dev). pub trait AccessKitEntityExt { /// Convert an entity to a stable [`NodeId`]. fn to_node_id(&self) -> NodeId; } impl AccessKitEntityExt for Entity { fn to_node_id(&self) -> NodeId { let id = NonZeroU128::new(self.to_bits() as u128 + 1); NodeId(id.unwrap()) } } /// Resource representing which entity has keyboard focus, if any. #[derive(Resource, Default, Deref, DerefMut)] pub struct Focus(Option); /// Plugin managing non-GUI aspects of integrating with accessibility APIs. pub struct AccessibilityPlugin; impl Plugin for AccessibilityPlugin { fn build(&self, app: &mut bevy_app::App) { app.init_resource::() .init_resource::(); } }