22
33use alloc:: { collections:: VecDeque , sync:: Arc } ;
44use bevy_input_focus:: InputFocus ;
5+ use core:: cell:: RefCell ;
56use std:: sync:: Mutex ;
67use winit:: event_loop:: ActiveEventLoop ;
78
@@ -16,13 +17,26 @@ use bevy_a11y::{
1617} ;
1718use bevy_app:: { App , Plugin , PostUpdate } ;
1819use bevy_derive:: { Deref , DerefMut } ;
19- use bevy_ecs:: { entity:: EntityHashMap , prelude:: * } ;
20+ use bevy_ecs:: { entity:: EntityHashMap , prelude:: * , system :: NonSendMarker } ;
2021use bevy_window:: { PrimaryWindow , Window , WindowClosed } ;
2122
23+ thread_local ! {
24+ /// Temporary storage of access kit adapter data to replace usage of `!Send` resources. This will be replaced with proper
25+ /// storage of `!Send` data after issue #17667 is complete.
26+ pub static ACCESS_KIT_ADAPTERS : RefCell <AccessKitAdapters > = const { RefCell :: new( AccessKitAdapters :: new( ) ) } ;
27+ }
28+
2229/// Maps window entities to their `AccessKit` [`Adapter`]s.
2330#[ derive( Default , Deref , DerefMut ) ]
2431pub struct AccessKitAdapters ( pub EntityHashMap < Adapter > ) ;
2532
33+ impl AccessKitAdapters {
34+ /// Creates a new empty `AccessKitAdapters`.
35+ pub const fn new ( ) -> Self {
36+ Self ( EntityHashMap :: new ( ) )
37+ }
38+ }
39+
2640/// Maps window entities to their respective [`ActionRequest`]s.
2741#[ derive( Resource , Default , Deref , DerefMut ) ]
2842pub struct WinitActionRequestHandlers ( pub EntityHashMap < Arc < Mutex < WinitActionRequestHandler > > > ) ;
@@ -144,14 +158,16 @@ pub(crate) fn prepare_accessibility_for_window(
144158}
145159
146160fn window_closed (
147- mut adapters : NonSendMut < AccessKitAdapters > ,
148161 mut handlers : ResMut < WinitActionRequestHandlers > ,
149162 mut events : EventReader < WindowClosed > ,
163+ _non_send_marker : NonSendMarker ,
150164) {
151- for WindowClosed { window, .. } in events. read ( ) {
152- adapters. remove ( window) ;
153- handlers. remove ( window) ;
154- }
165+ ACCESS_KIT_ADAPTERS . with_borrow_mut ( |adapters| {
166+ for WindowClosed { window, .. } in events. read ( ) {
167+ adapters. remove ( window) ;
168+ handlers. remove ( window) ;
169+ }
170+ } ) ;
155171}
156172
157173fn poll_receivers (
@@ -174,7 +190,6 @@ fn should_update_accessibility_nodes(
174190}
175191
176192fn update_accessibility_nodes (
177- mut adapters : NonSendMut < AccessKitAdapters > ,
178193 focus : Option < Res < InputFocus > > ,
179194 primary_window : Query < ( Entity , & Window ) , With < PrimaryWindow > > ,
180195 nodes : Query < (
@@ -184,35 +199,38 @@ fn update_accessibility_nodes(
184199 Option < & ChildOf > ,
185200 ) > ,
186201 node_entities : Query < Entity , With < AccessibilityNode > > ,
202+ _non_send_marker : NonSendMarker ,
187203) {
188- let Ok ( ( primary_window_id, primary_window) ) = primary_window. single ( ) else {
189- return ;
190- } ;
191- let Some ( adapter) = adapters. get_mut ( & primary_window_id) else {
192- return ;
193- } ;
194- let Some ( focus) = focus else {
195- return ;
196- } ;
197- if focus. is_changed ( ) || !nodes. is_empty ( ) {
198- // Don't panic if the focused entity does not currently exist
199- // It's probably waiting to be spawned
200- if let Some ( focused_entity) = focus. 0 {
201- if !node_entities. contains ( focused_entity) {
202- return ;
204+ ACCESS_KIT_ADAPTERS . with_borrow_mut ( |adapters| {
205+ let Ok ( ( primary_window_id, primary_window) ) = primary_window. single ( ) else {
206+ return ;
207+ } ;
208+ let Some ( adapter) = adapters. get_mut ( & primary_window_id) else {
209+ return ;
210+ } ;
211+ let Some ( focus) = focus else {
212+ return ;
213+ } ;
214+ if focus. is_changed ( ) || !nodes. is_empty ( ) {
215+ // Don't panic if the focused entity does not currently exist
216+ // It's probably waiting to be spawned
217+ if let Some ( focused_entity) = focus. 0 {
218+ if !node_entities. contains ( focused_entity) {
219+ return ;
220+ }
203221 }
204- }
205222
206- adapter. update_if_active ( || {
207- update_adapter (
208- nodes,
209- node_entities,
210- primary_window,
211- primary_window_id,
212- focus,
213- )
214- } ) ;
215- }
223+ adapter. update_if_active ( || {
224+ update_adapter (
225+ nodes,
226+ node_entities,
227+ primary_window,
228+ primary_window_id,
229+ focus,
230+ )
231+ } ) ;
232+ }
233+ } ) ;
216234}
217235
218236fn update_adapter (
@@ -290,8 +308,7 @@ pub struct AccessKitPlugin;
290308
291309impl Plugin for AccessKitPlugin {
292310 fn build ( & self , app : & mut App ) {
293- app. init_non_send_resource :: < AccessKitAdapters > ( )
294- . init_resource :: < WinitActionRequestHandlers > ( )
311+ app. init_resource :: < WinitActionRequestHandlers > ( )
295312 . add_event :: < ActionRequestWrapper > ( )
296313 . add_systems (
297314 PostUpdate ,
0 commit comments