2
2
3
3
use alloc:: { collections:: VecDeque , sync:: Arc } ;
4
4
use bevy_input_focus:: InputFocus ;
5
+ use core:: cell:: RefCell ;
5
6
use std:: sync:: Mutex ;
6
7
use winit:: event_loop:: ActiveEventLoop ;
7
8
@@ -16,13 +17,26 @@ use bevy_a11y::{
16
17
} ;
17
18
use bevy_app:: { App , Plugin , PostUpdate } ;
18
19
use bevy_derive:: { Deref , DerefMut } ;
19
- use bevy_ecs:: { entity:: EntityHashMap , prelude:: * } ;
20
+ use bevy_ecs:: { entity:: EntityHashMap , prelude:: * , system :: NonSendMarker } ;
20
21
use bevy_window:: { PrimaryWindow , Window , WindowClosed } ;
21
22
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
+
22
29
/// Maps window entities to their `AccessKit` [`Adapter`]s.
23
30
#[ derive( Default , Deref , DerefMut ) ]
24
31
pub struct AccessKitAdapters ( pub EntityHashMap < Adapter > ) ;
25
32
33
+ impl AccessKitAdapters {
34
+ /// Creates a new empty `AccessKitAdapters`.
35
+ pub const fn new ( ) -> Self {
36
+ Self ( EntityHashMap :: new ( ) )
37
+ }
38
+ }
39
+
26
40
/// Maps window entities to their respective [`ActionRequest`]s.
27
41
#[ derive( Resource , Default , Deref , DerefMut ) ]
28
42
pub struct WinitActionRequestHandlers ( pub EntityHashMap < Arc < Mutex < WinitActionRequestHandler > > > ) ;
@@ -144,14 +158,16 @@ pub(crate) fn prepare_accessibility_for_window(
144
158
}
145
159
146
160
fn window_closed (
147
- mut adapters : NonSendMut < AccessKitAdapters > ,
148
161
mut handlers : ResMut < WinitActionRequestHandlers > ,
149
162
mut events : EventReader < WindowClosed > ,
163
+ _non_send_marker : NonSendMarker ,
150
164
) {
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
+ } ) ;
155
171
}
156
172
157
173
fn poll_receivers (
@@ -174,7 +190,6 @@ fn should_update_accessibility_nodes(
174
190
}
175
191
176
192
fn update_accessibility_nodes (
177
- mut adapters : NonSendMut < AccessKitAdapters > ,
178
193
focus : Option < Res < InputFocus > > ,
179
194
primary_window : Query < ( Entity , & Window ) , With < PrimaryWindow > > ,
180
195
nodes : Query < (
@@ -184,35 +199,38 @@ fn update_accessibility_nodes(
184
199
Option < & ChildOf > ,
185
200
) > ,
186
201
node_entities : Query < Entity , With < AccessibilityNode > > ,
202
+ _non_send_marker : NonSendMarker ,
187
203
) {
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
+ }
203
221
}
204
- }
205
222
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
+ } ) ;
216
234
}
217
235
218
236
fn update_adapter (
@@ -290,8 +308,7 @@ pub struct AccessKitPlugin;
290
308
291
309
impl Plugin for AccessKitPlugin {
292
310
fn build ( & self , app : & mut App ) {
293
- app. init_non_send_resource :: < AccessKitAdapters > ( )
294
- . init_resource :: < WinitActionRequestHandlers > ( )
311
+ app. init_resource :: < WinitActionRequestHandlers > ( )
295
312
. add_event :: < ActionRequestWrapper > ( )
296
313
. add_systems (
297
314
PostUpdate ,
0 commit comments