PR #96 — Liquify undo (#97)

* fix(ui): route Liquify shortcuts before egui focus gate

* test(ui): cover Liquify undo with focused dialog controls
This commit is contained in:
Nigel Ihza Firdausy 2026-10-05 12:02:16 +07:00 committed by GitHub
parent def1402401
commit 3400412616
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 38 additions and 0 deletions

View File

@ -754,6 +754,38 @@ mod tests {
assert_eq!(app.session.active().unwrap().history.past_len(), before + 1); assert_eq!(app.session.active().unwrap().history.past_len(), before + 1);
} }
#[test]
fn shortcut_handler_undoes_liquify_even_when_egui_owns_keyboard_focus() {
let ctx = egui::Context::default();
let mut app = app_with_layer();
open(&mut app, &ctx).unwrap();
for ev in [
ToolEvent::Down { x: 40.0, y: 40.0, pressure: 1.0 },
ToolEvent::Move { x: 52.0, y: 40.0, pressure: 1.0 },
ToolEvent::Up { x: 52.0, y: 40.0 },
] {
pointer(&mut app, ev, egui::Modifiers::NONE);
}
assert_eq!(app.distort.liquify.as_ref().unwrap().strokes.len(), 1);
let raw = egui::RawInput {
events: vec![egui::Event::Key {
key: egui::Key::Z,
physical_key: None,
pressed: true,
repeat: false,
modifiers: egui::Modifiers::COMMAND,
}],
..Default::default()
};
let _ = ctx.run(raw, |ctx| {
ctx.memory_mut(|m| m.request_focus(egui::Id::new("liquify-slider-focus")));
assert!(ctx.egui_wants_keyboard_input());
crate::shortcuts::handle(&mut app, ctx);
});
assert_eq!(app.distort.liquify.as_ref().unwrap().strokes.len(), 0);
}
#[test] #[test]
fn menu_opens_the_dialog_and_routes_pointer_events() { fn menu_opens_the_dialog_and_routes_pointer_events() {
let ctx = egui::Context::default(); let ctx = egui::Context::default();

View File

@ -156,6 +156,12 @@ pub fn clipboard_keys(ctx: &egui::Context, typing: bool, raw: &mut egui::RawInpu
} }
pub fn handle(app: &mut PhotocraftApp, ctx: &egui::Context) { pub fn handle(app: &mut PhotocraftApp, ctx: &egui::Context) {
// Liquify is a full-window custom dialog with focusable sliders. egui can therefore claim
// keyboard input before the distortion-mode handler below runs. Give Liquify's local
// shortcuts first refusal (Undo, brush size, tool keys), but never steal keys from text edits.
if app.distort.liquify.is_some() && !ctx.text_edit_focused() {
crate::liquify_ui::keys(app, ctx);
}
if ctx.egui_wants_keyboard_input() || !app.ui.dialogs.is_empty() || app.discard.is_some() { if ctx.egui_wants_keyboard_input() || !app.ui.dialogs.is_empty() || app.discard.is_some() {
// Dialogs and focused sliders keep canvas zoom; a focused text field keeps its keys. // Dialogs and focused sliders keep canvas zoom; a focused text field keeps its keys.
if !ctx.text_edit_focused() { if !ctx.text_edit_focused() {