Fix #1367: a dialog opened from a menu takes the keyboard focus every time
A dialog opened by a click is drawn in the frame of that click, and in that frame egui takes the focus from any field the click missed. The first time a dialog's window shows, that frame only measures it, so its first field took the focus a frame later and kept it; every later time the field took it in the click's frame and lost it at once. The field now takes it the frame after the click.
This commit is contained in:
parent
0a357c68a9
commit
0765bc9bcd
|
|
@ -383,6 +383,13 @@ pub fn show(app: &mut VectorcraftApp, ctx: &egui::Context) {
|
|||
}
|
||||
m.get_temp::<bool>(focus_id).unwrap_or(false)
|
||||
});
|
||||
// Not in the frame of a click (the one on the menu item that opened it): egui takes the focus
|
||||
// from a field the click missed, so the field takes it a frame later (#1367).
|
||||
let clicked = ctx.input(|i| i.pointer.any_click());
|
||||
if focus_first && clicked {
|
||||
ctx.request_repaint();
|
||||
}
|
||||
let focus_first = focus_first && !clicked;
|
||||
let spec = spec(&d.kind);
|
||||
if let Some(window) = spec.window {
|
||||
return window(app, ctx);
|
||||
|
|
|
|||
|
|
@ -525,6 +525,47 @@ fn a_dialog_opens_with_its_first_field_focused_so_typing_and_enter_apply() {
|
|||
assert_eq!(node.appearance.effects.last().map(|e| e.params["scaleH"].clone()), Some(json!(50.0)));
|
||||
}
|
||||
|
||||
/// #1367: a dialog opened by a click (its menu item) is drawn in the frame of that click, where egui
|
||||
/// takes the focus from a field the click missed: its first field still has the focus, each time it
|
||||
/// opens.
|
||||
#[test]
|
||||
fn a_dialog_opened_by_a_click_focuses_its_first_field_each_time_it_opens() {
|
||||
let mut app = app();
|
||||
app.run("shape.rectangle", json!({"x": 10, "y": 10, "width": 40, "height": 20})).unwrap();
|
||||
let ctx = egui::Context::default();
|
||||
theme::install_fonts(&ctx);
|
||||
theme::apply(&ctx, Default::default());
|
||||
let frame = |app: &mut VectorcraftApp, events: Vec<egui::Event>| {
|
||||
let mut out = ctx.run_ui(egui::RawInput { events, ..Default::default() }, |ui| show(app, ui.ctx()));
|
||||
out.textures_delta.clear();
|
||||
};
|
||||
// A click away from the dialog, as on a menu item.
|
||||
let click = || {
|
||||
let (pos, button, modifiers) = (egui::pos2(5.0, 5.0), egui::PointerButton::Primary, egui::Modifiers::NONE);
|
||||
let press = |pressed| egui::Event::PointerButton { pos, button, pressed, modifiers };
|
||||
vec![egui::Event::PointerMoved(pos), press(true), press(false)]
|
||||
};
|
||||
type Open = fn(&mut VectorcraftApp);
|
||||
let opens: [(&str, Open); 2] = [
|
||||
("Convert to Shape", |app| drop(app.run("effect.dialog", json!({"effect": "convertToShape.rectangle"})))),
|
||||
("Rasterize", |app| crate::menus::invoke(app, "object.rasterize", json!({}))),
|
||||
];
|
||||
for (name, open) in opens {
|
||||
for turn in 1..=3 {
|
||||
open(&mut app);
|
||||
assert!(app.ui.dialog.is_some(), "{name}");
|
||||
frame(&mut app, click());
|
||||
frame(&mut app, vec![]);
|
||||
frame(&mut app, vec![]);
|
||||
assert!(ctx.memory(|m| m.focused()).is_some(), "{name}, turn {turn}");
|
||||
cancel(&mut app);
|
||||
// A frame without the dialog, as between two uses of it.
|
||||
frame(&mut app, vec![]);
|
||||
assert!(ctx.memory(|m| m.focused()).is_none(), "{name}, turn {turn}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// #1000: a count typed in Object › Create Object Mosaic… reaches the command (a whole number typed
|
||||
/// in a command's dialog is an integer), so the mosaic has that many columns, not the 10 × 10 grid.
|
||||
#[test]
|
||||
|
|
|
|||
Loading…
Reference in New Issue