Skip to content

Commit 4d8609b

Browse files
committed
bevy_winit changes
1 parent 671484e commit 4d8609b

File tree

7 files changed

+1870
-891
lines changed

7 files changed

+1870
-891
lines changed

crates/bevy_winit/src/accessibility.rs

Lines changed: 88 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,19 @@ use bevy_a11y::{
1414
use bevy_app::{App, Plugin, PostUpdate};
1515
use bevy_derive::{Deref, DerefMut};
1616
use bevy_ecs::{
17-
prelude::{DetectChanges, Entity, EventReader, EventWriter},
17+
prelude::{DetectChanges, Entity, EventReader, EventWriter, ThreadLocal, ThreadLocalResource},
1818
query::With,
19-
system::{NonSend, NonSendMut, Query, Res, ResMut, Resource},
19+
system::{Query, Res, ResMut, Resource},
2020
};
2121
use bevy_hierarchy::{Children, Parent};
2222
use bevy_utils::{default, HashMap};
2323
use bevy_window::{PrimaryWindow, Window, WindowClosed, WindowFocused};
2424

25-
/// Maps window entities to their `AccessKit` [`Adapter`]s.
26-
#[derive(Default, Deref, DerefMut)]
25+
/// Maps each window entity to its `AccessKit` [`Adapter`].
26+
///
27+
/// **Note:** This is a [`ThreadLocalResource`] because the macOS implementation of [`Adapter`]
28+
/// is not [`Send`](Send).
29+
#[derive(ThreadLocalResource, Default, Deref, DerefMut)]
2730
pub struct AccessKitAdapters(pub HashMap<Entity, Adapter>);
2831

2932
/// Maps window entities to their respective [`WinitActionHandler`]s.
@@ -43,35 +46,41 @@ impl ActionHandler for WinitActionHandler {
4346

4447
fn handle_window_focus(
4548
focus: Res<Focus>,
46-
adapters: NonSend<AccessKitAdapters>,
4749
mut focused: EventReader<WindowFocused>,
50+
mut main_thread: ThreadLocal,
4851
) {
49-
for event in focused.read() {
50-
if let Some(adapter) = adapters.get(&event.window) {
51-
adapter.update_if_active(|| {
52-
let focus_id = (*focus).unwrap_or_else(|| event.window);
53-
TreeUpdate {
54-
focus: if event.focused {
55-
Some(focus_id.to_node_id())
56-
} else {
57-
None
58-
},
59-
..default()
60-
}
61-
});
52+
main_thread.run(|tls| {
53+
let adapters = tls.resource::<AccessKitAdapters>();
54+
for event in focused.read() {
55+
if let Some(adapter) = adapters.get(&event.window) {
56+
adapter.update_if_active(|| {
57+
let focus_id = (*focus).unwrap_or_else(|| event.window);
58+
TreeUpdate {
59+
focus: if event.focused {
60+
Some(focus_id.to_node_id())
61+
} else {
62+
None
63+
},
64+
..default()
65+
}
66+
});
67+
}
6268
}
63-
}
69+
});
6470
}
6571

6672
fn window_closed(
67-
mut adapters: NonSendMut<AccessKitAdapters>,
6873
mut receivers: ResMut<WinitActionHandlers>,
6974
mut events: EventReader<WindowClosed>,
75+
mut main_thread: ThreadLocal,
7076
) {
71-
for WindowClosed { window, .. } in events.read() {
72-
adapters.remove(window);
73-
receivers.remove(window);
74-
}
77+
main_thread.run(|tls| {
78+
let mut adapters = tls.resource_mut::<AccessKitAdapters>();
79+
for WindowClosed { window, .. } in events.read() {
80+
adapters.remove(window);
81+
receivers.remove(window);
82+
}
83+
});
7584
}
7685

7786
fn poll_receivers(
@@ -87,7 +96,6 @@ fn poll_receivers(
8796
}
8897

8998
fn update_accessibility_nodes(
90-
adapters: NonSend<AccessKitAdapters>,
9199
focus: Res<Focus>,
92100
accessibility_requested: Res<AccessibilityRequested>,
93101
primary_window: Query<(Entity, &Window), With<PrimaryWindow>>,
@@ -98,70 +106,75 @@ fn update_accessibility_nodes(
98106
Option<&Parent>,
99107
)>,
100108
node_entities: Query<Entity, With<AccessibilityNode>>,
109+
mut main_thread: ThreadLocal,
101110
) {
102111
if !accessibility_requested.load(Ordering::SeqCst) {
103112
return;
104113
}
114+
105115
if let Ok((primary_window_id, primary_window)) = primary_window.get_single() {
106-
if let Some(adapter) = adapters.get(&primary_window_id) {
107-
let should_run = focus.is_changed() || !nodes.is_empty();
108-
if should_run {
109-
adapter.update_if_active(|| {
110-
let mut to_update = vec![];
111-
let mut has_focus = false;
112-
let mut name = None;
113-
if primary_window.focused {
114-
has_focus = true;
115-
let title = primary_window.title.clone();
116-
name = Some(title.into_boxed_str());
117-
}
118-
let focus_id = if has_focus {
119-
(*focus).or_else(|| Some(primary_window_id))
120-
} else {
121-
None
122-
};
123-
let mut root_children = vec![];
124-
for (entity, node, children, parent) in &nodes {
125-
let mut node = (**node).clone();
126-
if let Some(parent) = parent {
127-
if node_entities.get(**parent).is_err() {
116+
main_thread.run(|tls| {
117+
let adapters = tls.resource::<AccessKitAdapters>();
118+
if let Some(adapter) = adapters.get(&primary_window_id) {
119+
let should_run = focus.is_changed() || !nodes.is_empty();
120+
if should_run {
121+
adapter.update_if_active(|| {
122+
let mut to_update = vec![];
123+
let mut has_focus = false;
124+
let mut name = None;
125+
if primary_window.focused {
126+
has_focus = true;
127+
let title = primary_window.title.clone();
128+
name = Some(title.into_boxed_str());
129+
}
130+
let focus_id = if has_focus {
131+
(*focus).or_else(|| Some(primary_window_id))
132+
} else {
133+
None
134+
};
135+
let mut root_children = vec![];
136+
for (entity, node, children, parent) in &nodes {
137+
let mut node = (**node).clone();
138+
if let Some(parent) = parent {
139+
if node_entities.get(**parent).is_err() {
140+
root_children.push(entity.to_node_id());
141+
}
142+
} else {
128143
root_children.push(entity.to_node_id());
129144
}
130-
} else {
131-
root_children.push(entity.to_node_id());
132-
}
133-
if let Some(children) = children {
134-
for child in children {
135-
if node_entities.get(*child).is_ok() {
136-
node.push_child(child.to_node_id());
145+
if let Some(children) = children {
146+
for child in children {
147+
if node_entities.get(*child).is_ok() {
148+
node.push_child(child.to_node_id());
149+
}
137150
}
138151
}
152+
to_update.push((
153+
entity.to_node_id(),
154+
node.build(&mut NodeClassSet::lock_global()),
155+
));
139156
}
140-
to_update.push((
141-
entity.to_node_id(),
142-
node.build(&mut NodeClassSet::lock_global()),
143-
));
144-
}
145-
let mut root = NodeBuilder::new(Role::Window);
146-
if let Some(name) = name {
147-
root.set_name(name);
148-
}
149-
root.set_children(root_children);
150-
let root = root.build(&mut NodeClassSet::lock_global());
151-
let window_update = (primary_window_id.to_node_id(), root);
152-
to_update.insert(0, window_update);
153-
TreeUpdate {
154-
nodes: to_update,
155-
focus: focus_id.map(|v| v.to_node_id()),
156-
..default()
157-
}
158-
});
157+
let mut root = NodeBuilder::new(Role::Window);
158+
if let Some(name) = name {
159+
root.set_name(name);
160+
}
161+
root.set_children(root_children);
162+
let root = root.build(&mut NodeClassSet::lock_global());
163+
let window_update = (primary_window_id.to_node_id(), root);
164+
to_update.insert(0, window_update);
165+
TreeUpdate {
166+
nodes: to_update,
167+
focus: focus_id.map(|v| v.to_node_id()),
168+
..default()
169+
}
170+
});
171+
}
159172
}
160-
}
173+
});
161174
}
162175
}
163176

164-
/// Implements winit-specific `AccessKit` functionality.
177+
/// Implements [`winit`]-specific `AccessKit` functionality.
165178
pub struct AccessibilityPlugin;
166179

167180
impl Plugin for AccessibilityPlugin {

0 commit comments

Comments
 (0)