From 3301db5817aeb76aca3052b2d03924730d1829bd Mon Sep 17 00:00:00 2001 From: VoiceLessQ Date: Thu, 29 Oct 2026 14:48:55 -0200 Subject: [PATCH] Image Trace: starting a background trace asks for a frame The frame a trace starts in may already have asked for its next one before the trace started, so with no input the finished trace could wait. From the review of #4617. --- crates/ui-egui/src/tests/trace_runs.rs | 21 +++++++++++++++++++++ crates/ui-egui/src/trace_runs.rs | 4 ++++ 2 files changed, 25 insertions(+) diff --git a/crates/ui-egui/src/tests/trace_runs.rs b/crates/ui-egui/src/tests/trace_runs.rs index 9fbd1b2d6..d2de2f00f 100644 --- a/crates/ui-egui/src/tests/trace_runs.rs +++ b/crates/ui-egui/src/tests/trace_runs.rs @@ -76,6 +76,27 @@ fn make_traces_off_the_ui_thread_as_one_undo_step() { assert_eq!(app.session.doc().unwrap().history.undo.last().unwrap().label, "Image Trace (Make and Expand)"); } +/// Starting a trace asks for a frame, so its result is picked up without input: the frame that +/// started it may have asked for its next one before it did (#4617 review). +#[test] +fn starting_a_trace_asks_for_a_frame() { + let mut app = app(); + let ctx = egui::Context::default(); + app.adopt_context(&ctx); + for _ in 0..5 { + if !ctx.has_requested_repaint() { + break; + } + let mut out = ctx.run_ui(Default::default(), |_| {}); + out.textures_delta.clear(); + } + assert!(!ctx.has_requested_repaint(), "the context settled"); + crate::menus::invoke(&mut app, "imageTrace.make", json!({"preset": "Default"})); + assert_eq!(app.trace_runs.running.len(), 1); + assert!(ctx.has_requested_repaint()); + wait(&mut app); +} + /// Without threads (the web, `VECTORCRAFT_SYNC_OPEN`, unit tests that don't ask), Make traces at once. #[test] fn without_threads_make_traces_at_once() { diff --git a/crates/ui-egui/src/trace_runs.rs b/crates/ui-egui/src/trace_runs.rs index a5bf0fd5e..e05448b10 100644 --- a/crates/ui-egui/src/trace_runs.rs +++ b/crates/ui-egui/src/trace_runs.rs @@ -121,6 +121,10 @@ pub fn start(app: &mut VectorcraftApp, command: &str, p: Value, from_panel: bool let runs = &mut app.trace_runs; runs.next_id += 1; runs.running.push(Running { id: runs.next_id, doc, target, token, superseded: false, steps, from_panel, hidden: false, done }); + // This frame may have asked for its next one before the trace started (`tick`): ask now. + if let Some(ctx) = &app.ui_ctx { + ctx.request_repaint(); + } let status = format!("{}…", crate::i18n::msg(LABEL)); app.status(status.clone()); Ok(json!({ "background": true, "status": status }))