diff --git a/crates/ui-egui/src/chrome/tests.rs b/crates/ui-egui/src/chrome/tests.rs index e021354af..f32d3a944 100644 --- a/crates/ui-egui/src/chrome/tests.rs +++ b/crates/ui-egui/src/chrome/tests.rs @@ -995,10 +995,12 @@ fn tab_skips_the_isolation_bars_background() { }; frame(vec![]); let bar = egui::Rect::from_min_size(screen.min, egui::vec2(screen.width(), 24.0)); - let bar = ctx.viewport(|vp| vp.prev_pass.widgets.layers().flat_map(|(_, w)| w.iter()).find(|w| w.rect == bar).map(|w| w.id)); - let bar = bar.expect("the isolation bar"); + let back = egui::Rect::from_min_size(bar.min + egui::vec2(6.0, 3.0), egui::vec2(18.0, 18.0)); + let widget = + |rect: egui::Rect| ctx.viewport(|vp| vp.prev_pass.widgets.layers().flat_map(|(_, w)| w.iter()).find(|w| w.rect == rect).map(|w| w.id)); + let (bar, back) = (widget(bar).expect("the isolation bar"), widget(back).expect("the back button")); let stops = crate::widgets::accessibility_tests::tab_stops(&ctx, 10, frame); - assert!(!stops.is_empty(), "Tab reaches the back button and the breadcrumbs"); + assert!(stops.contains(&back), "Tab reaches the back button: {stops:?}"); assert!(!stops.contains(&bar), "{stops:?}"); } diff --git a/crates/ui-egui/src/dialogs/modal.rs b/crates/ui-egui/src/dialogs/modal.rs index 0303db8c6..6d9f91df3 100644 --- a/crates/ui-egui/src/dialogs/modal.rs +++ b/crates/ui-egui/src/dialogs/modal.rs @@ -21,7 +21,8 @@ pub(crate) fn show_at(ctx: &egui::Context, title: &str, id: Id, initial: Vec2 let dim = backdrop(); egui::Area::new(dim.id).order(dim.order).fixed_pos(egui::Pos2::ZERO).show(ctx, |ui| { // Modal, but the canvas isn't dimmed so previews stay readable (as in the reference app). - ui.allocate_rect(ctx.content_rect(), egui::Sense::click()); + // Not focusable (`Sense::click()` is): Tab goes through the dialog's controls, not the backdrop. + ui.allocate_rect(ctx.content_rect(), egui::Sense::CLICK); }); let shown = egui::Window::new(title) .id(id) diff --git a/crates/ui-egui/src/dialogs/tests_modal.rs b/crates/ui-egui/src/dialogs/tests_modal.rs index 80e403d83..c2b1daf06 100644 --- a/crates/ui-egui/src/dialogs/tests_modal.rs +++ b/crates/ui-egui/src/dialogs/tests_modal.rs @@ -133,10 +133,17 @@ fn tab_skips_the_band_that_moves_a_dialog() { settle(&ctx, &mut app); let band = modal::handle(id); assert!(ctx.read_response(band).is_some(), "{name}: the band is drawn"); + let window = ctx.memory(|m| m.area_rect(id)).unwrap_or_else(|| panic!("{name}: the window is drawn")); let stops = crate::widgets::accessibility_tests::tab_stops(&ctx, 30, |events| { frame(&ctx, &mut app, events); }); - assert!(!stops.is_empty(), "{name}: Tab reaches the dialog's controls"); + let inside = |s: &egui::Id| ctx.read_response(*s).is_some_and(|r| r.rect.is_positive() && window.contains_rect(r.rect)); + assert!(stops.iter().any(inside), "{name}: Tab reaches a control in the dialog: {stops:?}"); + let backdrop: Vec = ctx.viewport(|vp| { + vp.prev_pass.widgets.layers().filter(|(l, _)| **l == modal::backdrop()).flat_map(|(_, w)| w.iter()).map(|w| w.id).collect() + }); + assert!(!backdrop.is_empty(), "{name}: the backdrop is drawn"); + assert!(!stops.iter().any(|id| backdrop.contains(id)), "{name}: Tab stops on the backdrop: {stops:?}"); assert!(!stops.contains(&band), "{name}: {stops:?}"); } } diff --git a/crates/ui-egui/src/titlebar.rs b/crates/ui-egui/src/titlebar.rs index 5f2a12876..5e151e0c5 100644 --- a/crates/ui-egui/src/titlebar.rs +++ b/crates/ui-egui/src/titlebar.rs @@ -403,7 +403,9 @@ mod tests { let stops = crate::widgets::accessibility_tests::tab_stops(&ctx, 40, |events| { w.frame(events); }); - assert!(!stops.is_empty(), "Tab reaches the bar's controls"); + for c in CAPTIONS { + assert!(stops.contains(&caption_id(c)), "Tab reaches the {c:?} button: {stops:?}"); + } let regions: Vec = std::iter::once(Id::unique("titlebar-drag")).chain((0..8usize).map(|i| Id::unique(("titlebar-resize", i)))).collect(); assert!(!stops.iter().any(|id| regions.contains(id)), "{stops:?}"); } diff --git a/crates/ui-egui/src/toolbar/tests.rs b/crates/ui-egui/src/toolbar/tests.rs index 0feb1cabd..b0f8ad29e 100644 --- a/crates/ui-egui/src/toolbar/tests.rs +++ b/crates/ui-egui/src/toolbar/tests.rs @@ -1030,8 +1030,15 @@ fn tab_skips_the_grip_and_the_tear_off_bars() { .map(|w| w.id) }); let grip = grip.expect("the Tools panel's grip"); + // The Tools panel's tool buttons: 36 by 29 pt. + let buttons: Vec = ctx.viewport(|vp| { + vp.prev_pass.widgets.layers().flat_map(|(_, w)| w.iter()).filter(|w| w.rect.size() == vec2(36.0, PITCH - 1.0)).map(|w| w.id).collect() + }); + assert!(!buttons.is_empty(), "the Tools panel's buttons are drawn"); let stops = crate::widgets::accessibility_tests::tab_stops(&ctx, 120, frame); - assert!(!stops.is_empty(), "Tab reaches the tool buttons"); + assert!(stops.iter().any(|id| buttons.contains(id)), "Tab reaches the Tools panel's buttons: {stops:?}"); + let close = egui::Id::unique(("tool-flyout-close", "polygon")); + assert!(stops.contains(&close), "Tab reaches the strip's Put back in the toolbar button: {stops:?}"); for (name, id) in [("the grip", grip), ("the flyout's bar", bar_id("rectangle")), ("the strip's bar", bar_id("polygon"))] { assert!(!stops.contains(&id), "Tab stops on {name}: {stops:?}"); }