diff --git a/src/ui/local_link.rs b/src/ui/local_link.rs index 8a190f41..67e762e9 100644 --- a/src/ui/local_link.rs +++ b/src/ui/local_link.rs @@ -162,6 +162,11 @@ impl LocalLink { cx, tty7_core::host::HostId::LOCAL, ); + // …and re-runs every local window's sync: a window + // built while this link was still dialing is parked + // `Unprimed { dirty }` with nothing else scheduled to + // wake it (see `tree_sync::on_link_up`). + crate::ui::tree_sync::on_link_up(cx, tty7_core::host::HostId::LOCAL); } Err(e) => { // The next tick schedules the following attempt off diff --git a/src/ui/tree_sync.rs b/src/ui/tree_sync.rs index 98fde807..eb2fd8d7 100644 --- a/src/ui/tree_sync.rs +++ b/src/ui/tree_sync.rs @@ -852,6 +852,28 @@ pub(crate) fn sync_window(app: &Tty7App, cx: &mut App) { } } +/// A control link to `host` just came up (or came back): re-run the sync for +/// every window bound to that machine. +/// +/// This is the retry [`start_prime`]'s unreachable arm leaves behind. A window +/// built while the link was still dialing parks as `Unprimed { dirty }`, and +/// the only other thing that re-enters [`sync_window`] is the *next* +/// structural change — on a first launch that may never come, and a quit +/// before it comes loses the window's layout (the machine never heard of it). +/// The link supervisor calling this on connect is what turns "the reconnect +/// gets there first" from a hope into a mechanism. Harmless for windows that +/// are already synced: their diff is empty and queues nothing. +pub(crate) fn on_link_up(cx: &mut App, host: HostId) { + for (workspace, app) in crate::ui::windows::WindowRegistry::open_windows(cx) { + if WorkspaceStore::host_of(cx, workspace) != host { + continue; + } + if let Some(app) = app.upgrade() { + app.update(cx, |app, cx| sync_window(app, cx)); + } + } +} + /// Whether `client_ws`'s window has seen its machine's tree (or was declared /// authoritative). The gate for destructive acts an *empty* window licenses — /// a window whose hydration has not answered is empty because it is waiting,