forked from 1b-agent/opencadstudio-upstream
Save: don't wait forever for the thumbnail frame or screenshot
A save from the active drawing first redraws the viewport without its overlays and screenshots it for the file's preview. When the compositor delivered no frame or never answered the screenshot (an occluded or throttled Wayland window), the save never started: the input layer stayed hidden, so the window ignored the mouse and keyboard, and automation requests waited on the save forever. A timer now stands in for the frame, and the screenshot races a half-second timeout; whichever answers first runs the save, without the refreshed preview if it has to. Closes #1801 Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
854641bb55
commit
f07d6e19fc
2 files changed
+40
-9
No files matched your search
+33
-8
@@ -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<F>(
|
||||
slot: &std::sync::Mutex<Option<F>>,
|
||||
screenshot: Option<iced::window::Screenshot>,
|
||||
) -> Task<Message>
|
||||
where
|
||||
F: FnMut(Option<iced::window::Screenshot>) -> Task<Message>,
|
||||
{
|
||||
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)
|
||||
|
||||
+7
-1
@@ -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()
|
||||
};
|
||||
|
||||
Reference in new issue
Block a user