Replace bevy_a11y::Focus with InputFocus (#16863)
# Objective Bevy now has first-class input focus handling! We should use this for accessibility purpose via accesskit too. ## Solution - Removed bevy_a11y::Focus. - Replaced all usages of Focus with InputFocus - Changed the dependency tree so bevy_a11y relies on bevy_input_focus - Moved initialization of the focus (starts with the primary window) from bevy_window to bevy_input_focus to avoid circular dependencies (and it's cleaner) ## Testing TODO ## Migration Guide `bevy_a11y::Focus` has been replaced with `bevy_input_focus::Focus`.
This commit is contained in:
parent
6ca1e756dc
commit
fa6cabd432
@ -14,6 +14,7 @@ bevy_app = { path = "../bevy_app", version = "0.15.0-dev" }
|
||||
bevy_derive = { path = "../bevy_derive", version = "0.15.0-dev" }
|
||||
bevy_ecs = { path = "../bevy_ecs", version = "0.15.0-dev" }
|
||||
bevy_reflect = { path = "../bevy_reflect", version = "0.15.0-dev" }
|
||||
bevy_input_focus = { path = "../bevy_input_focus", version = "0.15.0-dev" }
|
||||
|
||||
accesskit = "0.17"
|
||||
|
||||
|
@ -22,11 +22,10 @@ use accesskit::Node;
|
||||
use bevy_app::Plugin;
|
||||
use bevy_derive::{Deref, DerefMut};
|
||||
use bevy_ecs::{
|
||||
prelude::{Component, Entity, Event, ReflectResource},
|
||||
prelude::{Component, Event},
|
||||
schedule::SystemSet,
|
||||
system::Resource,
|
||||
};
|
||||
use bevy_reflect::{std_traits::ReflectDefault, Reflect};
|
||||
|
||||
/// Wrapper struct for [`accesskit::ActionRequest`]. Required to allow it to be used as an `Event`.
|
||||
#[derive(Event, Deref, DerefMut)]
|
||||
@ -97,11 +96,6 @@ impl From<Node> for AccessibilityNode {
|
||||
}
|
||||
}
|
||||
|
||||
/// Resource representing which entity has keyboard focus, if any.
|
||||
#[derive(Resource, Default, Deref, DerefMut, Reflect)]
|
||||
#[reflect(Resource, Default)]
|
||||
pub struct Focus(pub Option<Entity>);
|
||||
|
||||
/// Set enum for the systems relating to accessibility
|
||||
#[derive(Debug, Hash, PartialEq, Eq, Clone, SystemSet)]
|
||||
pub enum AccessibilitySystem {
|
||||
@ -115,11 +109,8 @@ pub struct AccessibilityPlugin;
|
||||
|
||||
impl Plugin for AccessibilityPlugin {
|
||||
fn build(&self, app: &mut bevy_app::App) {
|
||||
app.register_type::<Focus>();
|
||||
|
||||
app.init_resource::<AccessibilityRequested>()
|
||||
.init_resource::<ManageAccessibilityUpdates>()
|
||||
.init_resource::<Focus>()
|
||||
.allow_ambiguous_component::<AccessibilityNode>();
|
||||
}
|
||||
}
|
||||
|
@ -18,13 +18,13 @@
|
||||
|
||||
pub mod tab_navigation;
|
||||
|
||||
use bevy_app::{App, Plugin, PreUpdate};
|
||||
use bevy_app::{App, Plugin, PreUpdate, Startup};
|
||||
use bevy_ecs::{
|
||||
component::Component,
|
||||
entity::Entity,
|
||||
event::{Event, EventReader},
|
||||
query::{QueryData, With},
|
||||
system::{Commands, Query, Res, Resource, SystemParam},
|
||||
system::{Commands, Query, Res, ResMut, Resource, Single, SystemParam},
|
||||
traversal::Traversal,
|
||||
world::{Command, DeferredWorld, World},
|
||||
};
|
||||
@ -149,12 +149,21 @@ pub struct InputDispatchPlugin;
|
||||
|
||||
impl Plugin for InputDispatchPlugin {
|
||||
fn build(&self, app: &mut App) {
|
||||
app.insert_resource(InputFocus(None))
|
||||
app.add_systems(Startup, set_initial_focus)
|
||||
.insert_resource(InputFocus(None))
|
||||
.insert_resource(InputFocusVisible(false))
|
||||
.add_systems(PreUpdate, dispatch_keyboard_input);
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets the initial focus to the primary window, if any.
|
||||
pub fn set_initial_focus(
|
||||
mut input_focus: ResMut<InputFocus>,
|
||||
window: Single<Entity, With<PrimaryWindow>>,
|
||||
) {
|
||||
input_focus.0 = Some(*window);
|
||||
}
|
||||
|
||||
/// System which dispatches keyboard input events to the focused entity, or to the primary window
|
||||
/// if no entity has focus.
|
||||
fn dispatch_keyboard_input(
|
||||
@ -377,6 +386,9 @@ mod tests {
|
||||
};
|
||||
app.world_mut().spawn((window, PrimaryWindow));
|
||||
|
||||
// Run the world for a single frame to set up the initial focus
|
||||
app.update();
|
||||
|
||||
let entity_a = app
|
||||
.world_mut()
|
||||
.spawn((GatherKeyboardEvents::default(), SetFocusOnAdd))
|
||||
|
@ -13,7 +13,6 @@ serialize = ["serde", "smol_str/serde", "bevy_ecs/serialize"]
|
||||
|
||||
[dependencies]
|
||||
# bevy
|
||||
bevy_a11y = { path = "../bevy_a11y", version = "0.15.0-dev" }
|
||||
bevy_app = { path = "../bevy_app", version = "0.15.0-dev" }
|
||||
bevy_ecs = { path = "../bevy_ecs", version = "0.15.0-dev" }
|
||||
bevy_input = { path = "../bevy_input", version = "0.15.0-dev" }
|
||||
|
@ -16,8 +16,6 @@ extern crate alloc;
|
||||
use alloc::sync::Arc;
|
||||
use std::sync::Mutex;
|
||||
|
||||
use bevy_a11y::Focus;
|
||||
|
||||
mod event;
|
||||
mod monitor;
|
||||
mod raw_handle;
|
||||
@ -118,17 +116,10 @@ impl Plugin for WindowPlugin {
|
||||
.add_event::<AppLifecycle>();
|
||||
|
||||
if let Some(primary_window) = &self.primary_window {
|
||||
let initial_focus = app
|
||||
.world_mut()
|
||||
.spawn(primary_window.clone())
|
||||
.insert((
|
||||
PrimaryWindow,
|
||||
RawHandleWrapperHolder(Arc::new(Mutex::new(None))),
|
||||
))
|
||||
.id();
|
||||
if let Some(mut focus) = app.world_mut().get_resource_mut::<Focus>() {
|
||||
**focus = Some(initial_focus);
|
||||
}
|
||||
app.world_mut().spawn(primary_window.clone()).insert((
|
||||
PrimaryWindow,
|
||||
RawHandleWrapperHolder(Arc::new(Mutex::new(None))),
|
||||
));
|
||||
}
|
||||
|
||||
match self.exit_condition {
|
||||
|
@ -29,6 +29,7 @@ bevy_derive = { path = "../bevy_derive", version = "0.15.0-dev" }
|
||||
bevy_ecs = { path = "../bevy_ecs", version = "0.15.0-dev" }
|
||||
bevy_hierarchy = { path = "../bevy_hierarchy", version = "0.15.0-dev" }
|
||||
bevy_input = { path = "../bevy_input", version = "0.15.0-dev" }
|
||||
bevy_input_focus = { path = "../bevy_input_focus", version = "0.15.0-dev" }
|
||||
bevy_log = { path = "../bevy_log", version = "0.15.0-dev" }
|
||||
bevy_math = { path = "../bevy_math", version = "0.15.0-dev" }
|
||||
bevy_reflect = { path = "../bevy_reflect", version = "0.15.0-dev" }
|
||||
|
@ -1,6 +1,7 @@
|
||||
//! Helpers for mapping window entities to accessibility types
|
||||
|
||||
use alloc::{collections::VecDeque, sync::Arc};
|
||||
use bevy_input_focus::InputFocus;
|
||||
use std::sync::Mutex;
|
||||
|
||||
use accesskit::{
|
||||
@ -10,13 +11,14 @@ use accesskit::{
|
||||
use accesskit_winit::Adapter;
|
||||
use bevy_a11y::{
|
||||
AccessibilityNode, AccessibilityRequested, AccessibilitySystem,
|
||||
ActionRequest as ActionRequestWrapper, Focus, ManageAccessibilityUpdates,
|
||||
ActionRequest as ActionRequestWrapper, ManageAccessibilityUpdates,
|
||||
};
|
||||
use bevy_app::{App, Plugin, PostUpdate};
|
||||
use bevy_derive::{Deref, DerefMut};
|
||||
use bevy_ecs::{
|
||||
change_detection::DetectChanges,
|
||||
entity::EntityHashMap,
|
||||
prelude::{DetectChanges, Entity, EventReader, EventWriter},
|
||||
prelude::{Entity, EventReader, EventWriter},
|
||||
query::With,
|
||||
schedule::IntoSystemConfigs,
|
||||
system::{NonSendMut, Query, Res, ResMut, Resource},
|
||||
@ -179,7 +181,7 @@ fn should_update_accessibility_nodes(
|
||||
|
||||
fn update_accessibility_nodes(
|
||||
mut adapters: NonSendMut<AccessKitAdapters>,
|
||||
focus: Res<Focus>,
|
||||
focus: Res<InputFocus>,
|
||||
primary_window: Query<(Entity, &Window), With<PrimaryWindow>>,
|
||||
nodes: Query<(
|
||||
Entity,
|
||||
@ -218,7 +220,7 @@ fn update_adapter(
|
||||
node_entities: Query<Entity, With<AccessibilityNode>>,
|
||||
primary_window: &Window,
|
||||
primary_window_id: Entity,
|
||||
focus: Res<Focus>,
|
||||
focus: Res<InputFocus>,
|
||||
) -> TreeUpdate {
|
||||
let mut to_update = vec![];
|
||||
let mut window_children = vec![];
|
||||
@ -241,7 +243,7 @@ fn update_adapter(
|
||||
TreeUpdate {
|
||||
nodes: to_update,
|
||||
tree: None,
|
||||
focus: NodeId(focus.unwrap_or(primary_window_id).to_bits()),
|
||||
focus: NodeId(focus.0.unwrap_or(primary_window_id).to_bits()),
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user