Fix disabled widgets "eating" focus (#5370)
- fixes https://github.com/emilk/egui/issues/5359 For the test I added a `Harness::press_key` function. We should eventually add these to kittest, probably via a trait one can implement for the `Harness` but for now this should do.
This commit is contained in:
parent
83a30064f4
commit
9ecc0b232c
|
|
@ -1229,6 +1229,7 @@ dependencies = [
|
||||||
"ahash",
|
"ahash",
|
||||||
"backtrace",
|
"backtrace",
|
||||||
"document-features",
|
"document-features",
|
||||||
|
"egui_kittest",
|
||||||
"emath",
|
"emath",
|
||||||
"epaint",
|
"epaint",
|
||||||
"log",
|
"log",
|
||||||
|
|
|
||||||
|
|
@ -98,3 +98,7 @@ log = { workspace = true, optional = true }
|
||||||
puffin = { workspace = true, optional = true }
|
puffin = { workspace = true, optional = true }
|
||||||
ron = { workspace = true, optional = true }
|
ron = { workspace = true, optional = true }
|
||||||
serde = { workspace = true, optional = true, features = ["derive", "rc"] }
|
serde = { workspace = true, optional = true, features = ["derive", "rc"] }
|
||||||
|
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
egui_kittest = { workspace = true, features = ["wgpu", "snapshot"] }
|
||||||
|
|
|
||||||
|
|
@ -1160,6 +1160,8 @@ impl Context {
|
||||||
/// same widget, then `allow_focus` should only be true once (like in [`Ui::new`] (true) and [`Ui::remember_min_rect`] (false)).
|
/// same widget, then `allow_focus` should only be true once (like in [`Ui::new`] (true) and [`Ui::remember_min_rect`] (false)).
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
pub(crate) fn create_widget(&self, w: WidgetRect, allow_focus: bool) -> Response {
|
pub(crate) fn create_widget(&self, w: WidgetRect, allow_focus: bool) -> Response {
|
||||||
|
let interested_in_focus = w.enabled && w.sense.focusable && w.layer_id.allow_interaction();
|
||||||
|
|
||||||
// Remember this widget
|
// Remember this widget
|
||||||
self.write(|ctx| {
|
self.write(|ctx| {
|
||||||
let viewport = ctx.viewport();
|
let viewport = ctx.viewport();
|
||||||
|
|
@ -1169,12 +1171,12 @@ impl Context {
|
||||||
// but also to know when we have reached the widget we are checking for cover.
|
// but also to know when we have reached the widget we are checking for cover.
|
||||||
viewport.this_pass.widgets.insert(w.layer_id, w);
|
viewport.this_pass.widgets.insert(w.layer_id, w);
|
||||||
|
|
||||||
if allow_focus && w.sense.focusable {
|
if allow_focus && interested_in_focus {
|
||||||
ctx.memory.interested_in_focus(w.id);
|
ctx.memory.interested_in_focus(w.id);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if allow_focus && (!w.enabled || !w.sense.focusable || !w.layer_id.allow_interaction()) {
|
if allow_focus && !interested_in_focus {
|
||||||
// Not interested or allowed input:
|
// Not interested or allowed input:
|
||||||
self.memory_mut(|mem| mem.surrender_focus(w.id));
|
self.memory_mut(|mem| mem.surrender_focus(w.id));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
use egui::Button;
|
||||||
|
use egui_kittest::kittest::Queryable;
|
||||||
|
use egui_kittest::Harness;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
pub fn focus_should_skip_over_disabled_buttons() {
|
||||||
|
let mut harness = Harness::new_ui(|ui| {
|
||||||
|
ui.add(Button::new("Button 1"));
|
||||||
|
ui.add_enabled(false, Button::new("Button Disabled"));
|
||||||
|
ui.add(Button::new("Button 3"));
|
||||||
|
});
|
||||||
|
|
||||||
|
harness.press_key(egui::Key::Tab);
|
||||||
|
harness.run();
|
||||||
|
|
||||||
|
let button_1 = harness.get_by_name("Button 1");
|
||||||
|
assert!(button_1.is_focused());
|
||||||
|
|
||||||
|
harness.press_key(egui::Key::Tab);
|
||||||
|
harness.run();
|
||||||
|
|
||||||
|
let button_3 = harness.get_by_name("Button 3");
|
||||||
|
assert!(button_3.is_focused());
|
||||||
|
|
||||||
|
harness.press_key(egui::Key::Tab);
|
||||||
|
harness.run();
|
||||||
|
|
||||||
|
let button_1 = harness.get_by_name("Button 1");
|
||||||
|
assert!(button_1.is_focused());
|
||||||
|
}
|
||||||
|
|
@ -249,6 +249,25 @@ impl<'a, State> Harness<'a, State> {
|
||||||
pub fn state_mut(&mut self) -> &mut State {
|
pub fn state_mut(&mut self) -> &mut State {
|
||||||
&mut self.state
|
&mut self.state
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Press a key.
|
||||||
|
/// This will create a key down event and a key up event.
|
||||||
|
pub fn press_key(&mut self, key: egui::Key) {
|
||||||
|
self.input.events.push(egui::Event::Key {
|
||||||
|
key,
|
||||||
|
pressed: true,
|
||||||
|
modifiers: Default::default(),
|
||||||
|
repeat: false,
|
||||||
|
physical_key: None,
|
||||||
|
});
|
||||||
|
self.input.events.push(egui::Event::Key {
|
||||||
|
key,
|
||||||
|
pressed: false,
|
||||||
|
modifiers: Default::default(),
|
||||||
|
repeat: false,
|
||||||
|
physical_key: None,
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Utilities for stateless harnesses.
|
/// Utilities for stateless harnesses.
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue