Fix AccessKit node bounds (#18706)

# Objective

Fixes #18685

## Solution

* Don't apply the camera translation.
* Calculate the min and max bounds of the accessibility node rect taking
the UI translation relative to its center not the top-left corner.

## Testing

Install [NVDA](https://www.nvaccess.org/). In NVDA set `Preferences ->
Settings -> Vision -> Enable Highlighting`.

Then run bevy's `tab_navigation` example:
```
cargo run --example tab_navigation
```
If everything is working correctly, NVDA should draw a border around the
currently selected tab button:

![Screenshot 2025-04-07
130523](https://github.com/user-attachments/assets/07d9a795-5d55-4b61-9602-2e8917020245)
This commit is contained in:
ickshonpe 2025-04-08 02:42:02 +01:00 committed by François Mockers
parent c439fdb34c
commit 3cd83031e1

View File

@ -13,7 +13,8 @@ use bevy_ecs::{
system::{Commands, Query},
world::Ref,
};
use bevy_render::{camera::CameraUpdateSystem, prelude::Camera};
use bevy_math::Vec3Swizzles;
use bevy_render::camera::CameraUpdateSystem;
use bevy_transform::prelude::GlobalTransform;
use accesskit::{Node, Rect, Role};
@ -36,28 +37,20 @@ fn calc_label(
}
fn calc_bounds(
camera: Query<(&Camera, &GlobalTransform)>,
mut nodes: Query<(
&mut AccessibilityNode,
Ref<ComputedNode>,
Ref<GlobalTransform>,
)>,
) {
if let Ok((camera, camera_transform)) = camera.single() {
for (mut accessible, node, transform) in &mut nodes {
if node.is_changed() || transform.is_changed() {
if let Ok(translation) =
camera.world_to_viewport(camera_transform, transform.translation())
{
let bounds = Rect::new(
translation.x.into(),
translation.y.into(),
(translation.x + node.size.x).into(),
(translation.y + node.size.y).into(),
);
accessible.set_bounds(bounds);
}
}
for (mut accessible, node, transform) in &mut nodes {
if node.is_changed() || transform.is_changed() {
let center = transform.translation().xy();
let half_size = 0.5 * node.size;
let min = center - half_size;
let max = center + half_size;
let bounds = Rect::new(min.x as f64, min.y as f64, max.x as f64, max.y as f64);
accessible.set_bounds(bounds);
}
}
}