1
0
mirror of https://github.com/emilk/egui.git synced 2026-06-26 14:49:06 -04:00

Group AccessKit nodes by Ui (#7386)

* closes https://github.com/emilk/egui/issues/5674

This changes egui to create an AccessKit node for each `Ui`. I'm not
sure if this alone will directly improve accessibility, but it should
make it easier to create the correct parent / child relations (e.g.
grouping menus as children of menu buttons).
Instead of having a global stack of parent ids, they are now passed via
a parent_id field in `UiBuilder`.

If having all these `GenericContainer` nodes somehow is bad for
accessibility, the PR could also be changed to only create nodes if
there is actually some accessibility info with it (the relevant is
currently commented-out in the PR). But I think screen readers should
just ignore these nodes, so it should be fine? We could also use this as
motivation to git red of some unnecessary wrapped `Ui`s, e.g.
CentralPanel creates 3 Uis when 2 should be enough (the initial Ui and a
Frame, maybe we could even only show the `Frame` if we can give it an
UiBuilder and somehow show the Frame with `Ui::new`).

Here is a screenshot from the accessibility inspector
(https://github.com/emilk/egui/pull/7368) with this PR:

<img width="431" height="744" alt="Screenshot 2025-07-24 at 12 09 55"
src="https://github.com/user-attachments/assets/6c4e5ff6-5c38-450e-9500-0776c9018d8c"
/>

Without this PR:


https://github.com/user-attachments/assets/270e32fc-9c7a-4dad-8c90-7638c487a602
This commit is contained in:
Lucas Meurer
2025-10-08 11:30:32 +02:00
committed by GitHub
parent 6a49c9ad6b
commit 3fdc5641aa
14 changed files with 302 additions and 249 deletions

View File

@@ -1,3 +1,4 @@
use egui::accesskit::Role;
use egui::load::SizedTexture;
use egui::{
Align, AtomExt as _, AtomLayout, Button, Color32, ColorImage, Direction, DragValue, Event,
@@ -277,8 +278,8 @@ impl<'a> VisualTests<'a> {
node.hover();
});
self.add("pressed", |harness| {
harness.get_next().hover();
let rect = harness.get_next().rect();
harness.get_next_widget().hover();
let rect = harness.get_next_widget().rect();
harness.input_mut().events.push(Event::PointerButton {
button: PointerButton::Primary,
pos: rect.center(),
@@ -329,7 +330,7 @@ impl<'a> VisualTests<'a> {
pub fn add_node(&mut self, name: &str, test: impl FnOnce(&Node<'_>)) {
self.add(name, |harness| {
let node = harness.get_next();
let node = harness.get_next_widget();
test(&node);
});
}
@@ -375,11 +376,13 @@ impl<'a> VisualTests<'a> {
}
trait HarnessExt {
fn get_next(&self) -> Node<'_>;
fn get_next_widget(&self) -> Node<'_>;
}
impl HarnessExt for Harness<'_> {
fn get_next(&self) -> Node<'_> {
self.get_all(by()).next().unwrap()
fn get_next_widget(&self) -> Node<'_> {
self.get_all(by().predicate(|node| node.role() != Role::GenericContainer))
.next()
.unwrap()
}
}