forked from 1b-agent/opencadstudio-upstream
feat: draw a notice for one frame before rebuilding a layout
Switching to a Layout stops the main thread long enough that the compositor decides the application has stopped responding and offers to kill it. The switch itself is not the problem — `layout-switch` reports about 10 ms — it is the frame after it, which rebuilds the whole wire set. That frame now has a cheap one in front of it. `layout_settling` is set when the switch takes, and while it holds, the viewport is replaced by a centered "Preparing layout…" on the canvas background. No shader widget means no scene primitive, so `prepare` has nothing to do and the frame costs nothing. A `window::frames` subscription clears the flag, which is the guarantee this needs: that callback runs once a frame has actually been presented, so the notice is on screen and the compositor has been answered before the expensive frame starts. The deferral is of the *frame*, not the switch. Two callers depend on the switch having completed when it returns — one calls `fit_all` immediately after, another compares `current_layout` — so deferring the switch itself would have broken both. This restarts the compositor's timer immediately before the slow frame and replaces a stale window with something that says what is happening. It does not make the slow frame fast: if the rebuild still exceeds the compositor's timeout the dialog can return, and the durable fix is the 2 s `memo_miss` behind it, which is a separate change. Only `en-US` is validated against at build time; Greek is filled in too since it is in use here, and the rest fall back until translated. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
d9a1d55f2e
commit
09838be9ec
6 files changed
+62
-1
No files matched your search
@@ -1055,6 +1055,15 @@ pub(super) struct OpenCADStudio {
|
||||
/// `Some` while a CAD file is loading — drives the modal overlay.
|
||||
/// Cleared when the load finishes, errors, or the user cancels.
|
||||
pub(super) opening: Option<OpenProgress>,
|
||||
/// Set the moment a layout switch changes `current_layout`, cleared on the
|
||||
/// next presented frame.
|
||||
///
|
||||
/// The switch itself costs about 10 ms; the frame after it rebuilds the
|
||||
/// whole wire set and can block the main thread for seconds. While this is
|
||||
/// set the viewport is replaced by a notice, so that frame is cheap — which
|
||||
/// gives the compositor an answer, and the user something other than a
|
||||
/// stale window, immediately before the expensive one.
|
||||
pub(super) layout_settling: bool,
|
||||
open_job_serial: u64,
|
||||
/// Last repair or failed-open report shown in the recovery modal.
|
||||
recovery_report: Option<crate::io::recovery::RecoveryReport>,
|
||||
@@ -2283,6 +2292,9 @@ pub enum Message {
|
||||
/// Timer pulse while the cursor is dwelling on a grip; drives the
|
||||
/// dwell-to-popup transition without requiring further mouse motion.
|
||||
GripDwellTick,
|
||||
/// One frame has been presented since a layout switch; the next may do the
|
||||
/// expensive rebuild.
|
||||
LayoutSettled,
|
||||
/// Timer pulse while a rollover hit-test is queued; fires when the
|
||||
/// cursor has been still long enough to safely run the pick.
|
||||
HoverDwellTick,
|
||||
@@ -3484,6 +3496,7 @@ impl OpenCADStudio {
|
||||
print_all_plot_window_prev: None,
|
||||
print_all_plot_setup_prev: None,
|
||||
opening: None,
|
||||
layout_settling: false,
|
||||
open_job_serial: 0,
|
||||
recovery_report: None,
|
||||
pending_opens: std::collections::VecDeque::new(),
|
||||
|
||||
Reference in new issue
Block a user