diff --git a/src/app/update/file.rs b/src/app/update/file.rs index c4a7b38bc..2cd0935b8 100644 --- a/src/app/update/file.rs +++ b/src/app/update/file.rs @@ -3578,14 +3578,39 @@ impl OpenCADStudio { ) }; match capture_window { - Some(window) => iced::window::screenshot(window) - .map(Some) - .then(move |screenshot| { - Task::batch([ - Task::done(Message::ThumbnailCaptureFinished), - run_save(screenshot), - ]) - }), + // The screenshot may never come back (a window the compositor + // does not draw), so it races a short timeout: whichever answers + // first runs the save, with or without the picture. + Some(window) => { + fn finish( + slot: &std::sync::Mutex>, + screenshot: Option, + ) -> Task + where + F: FnMut(Option) -> Task, + { + match slot.lock().ok().and_then(|mut run| run.take()) { + Some(mut run_save) => Task::batch([ + Task::done(Message::ThumbnailCaptureFinished), + run_save(screenshot), + ]), + None => Task::none(), + } + } + let slot = std::sync::Arc::new(std::sync::Mutex::new(Some(run_save))); + let (shot_slot, timeout_slot) = (slot.clone(), slot); + let (tx, rx) = iced::futures::channel::oneshot::channel::<()>(); + std::thread::spawn(move || { + std::thread::sleep(std::time::Duration::from_millis(500)); + let _ = tx.send(()); + }); + Task::batch([ + iced::window::screenshot(window) + .map(Some) + .then(move |screenshot| finish(&shot_slot, screenshot)), + Task::perform(rx, |_| ()).then(move |_| finish(&timeout_slot, None)), + ]) + } None => { self.thumbnail_capture_clean = false; run_save(None) diff --git a/src/app/view/mod.rs b/src/app/view/mod.rs index 3e767f6e2..e2f9936d4 100644 --- a/src/app/view/mod.rs +++ b/src/app/view/mod.rs @@ -2861,8 +2861,14 @@ impl OpenCADStudio { } else { Subscription::none() }; + // A compositor that delivers no frame (an occluded or throttled + // window) must not hold the save: a timer goes ahead without it. let thumbnail_capture = if self.thumbnail_capture_clean { - window::frames().map(|_| Message::ThumbnailCaptureFrame) + Subscription::batch([ + window::frames().map(|_| Message::ThumbnailCaptureFrame), + iced::time::every(std::time::Duration::from_millis(300)) + .map(|_| Message::ThumbnailCaptureFrame), + ]) } else { Subscription::none() };