Cryptomatte eyedropper: Esc that closes a dialog keeps it armed (#473)

The Esc that closed New Solid or Composition Settings also disarmed the
eyedropper. An open dialog now takes Esc like a focused text field or an
open popup, so that Esc only closes the dialog and the next one disarms.
long_sequence asserts both instead of logging a finding.
This commit is contained in:
Matej Kozlovský committed 2026-11-03 08:56:53 +01:00
1 parent 0d1c5c08bf
commit f8463fcf7e
2 files changed
+16 -11

No files matched your search

+8 -6
View File
@@ -97,8 +97,9 @@ struct State {
/// The waiting clicks took the focus from a text field (the Selection being typed): they
/// are made once it has committed, on top of what it committed.
after_typing: bool,
/// A text field or a popup had the keyboard the pass before: its Esc isn't the pick's
/// (egui lets go of the focus and closes popups before the viewer runs).
/// A text field, a popup or a dialog had the keyboard the pass before: its Esc isn't the
/// pick's (egui lets go of the focus and closes popups, and Esc closes the dialog, before
/// the viewer runs).
esc_taken: bool,
/// The press of the click in progress.
press: Option<Press>,
@@ -507,12 +508,13 @@ fn draw_status_chip(app: &mut EffectcraftApp, ctx: &egui::Context, painter: &egu
painter.galley(chip.left_center() + vec2(12.0, -galley.size().y / 2.0), galley, colour);
}
/// Esc disarms the eyedropper only when no text field or popup had the keyboard this pass or
/// the pass before (egui lets go of the focus and closes popups before the viewer runs).
/// Esc disarms the eyedropper only when no text field, popup, or dialog had the keyboard this
/// pass or the pass before (egui lets go of the focus and closes popups, and Esc closes the
/// dialog, before the viewer runs).
fn handle_escape(app: &mut EffectcraftApp, ui: &mut egui::Ui, st: &mut State) {
let ctx = ui.ctx();
// (Esc in a text field, the Selection being typed, only ends the typing; in a menu, it.)
let esc_taken = std::mem::replace(&mut st.esc_taken, ctx.text_edit_focused() || egui::Popup::is_any_open(ctx));
// (Esc in a text field, the Selection being typed, only ends the typing; in a menu or dialog, it.)
let esc_taken = std::mem::replace(&mut st.esc_taken, ctx.text_edit_focused() || egui::Popup::is_any_open(ctx) || app.dialog.is_some());
if ui.input(|i| i.key_pressed(egui::Key::Escape)) && !esc_taken && !st.esc_taken {
app.ui.fx_pick = None;
app.ui.status.clear();
@@ -697,16 +697,19 @@ fn long_sequence(tag: &str, size: egui::Vec2, res: Resolution) {
for _ in 0..3 {
step_history(&mut h, &f, &mut m, dims, false, "undo before Ctrl+Y");
}
let armed = m.armed;
if m.armed.is_none() {
let l = if m.state().iter().find(|l| l.id == pl).and_then(|l| l.crypto()).is_some() { pl } else { pre };
run_step(&mut h, &f, &mut m, dims, &Arm(l), 99);
}
key(&mut h, Key::Y, CTRL);
assert!(h.state().dialog.is_some(), "Ctrl+Y opens the New Solid dialog");
assert_eq!(h.state().session.history.redo.len(), 3, "Ctrl+Y doesn't redo");
key(&mut h, Key::Escape, Modifiers::NONE);
assert!(h.state().dialog.is_none());
if armed.is_some() && h.state().ui.fx_pick.is_none() {
eprintln!("FINDING {tag}: Esc that closed the New Solid dialog also disarmed the eyedropper");
m.armed = None;
}
assert!(h.state().ui.fx_pick.is_some(), "Esc that closes the New Solid dialog keeps the eyedropper armed");
key(&mut h, Key::Escape, Modifiers::NONE);
assert!(h.state().ui.fx_pick.is_none(), "a second Esc disarms");
m.armed = None;
verify(&mut h, &f, &mut m, dims, "after Ctrl+Y and Esc");
// Undo partway, then a new pick: no redo left, the undone steps kept as a branch.
for k in 0..4 {