From 3cd83031e1886b25435de2ed093d689d6accde95 Mon Sep 17 00:00:00 2001 From: ickshonpe Date: Tue, 8 Apr 2025 02:42:02 +0100 Subject: [PATCH] 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) --- crates/bevy_ui/src/accessibility.rs | 27 ++++++++++----------------- 1 file changed, 10 insertions(+), 17 deletions(-) diff --git a/crates/bevy_ui/src/accessibility.rs b/crates/bevy_ui/src/accessibility.rs index d9ada994a1..3b0e6538f0 100644 --- a/crates/bevy_ui/src/accessibility.rs +++ b/crates/bevy_ui/src/accessibility.rs @@ -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, Ref, )>, ) { - 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); } } }