| ... | ... | @@ -6565,7 +6565,7 @@ impl App { |
| 6565 | 6565 | .map(|outline| (&outline.id, outline.document()))); |
| 6566 | 6566 | state.session.is_none() && !unchanged |
| 6567 | 6567 | }) else { |
| 6568 | | return self.exit(event_loop); |
| 6568 | return event_loop.exit(); |
| 6569 | 6569 | }; |
| 6570 | 6570 | crate::confirm( |
| 6571 | 6571 | "Discard this page?", |
| ... | ... | @@ -6578,19 +6578,12 @@ impl App { |
| 6578 | 6578 | }), |
| 6579 | 6579 | ); |
| 6580 | 6580 | } |
| 6581 | | |
| 6582 | | fn exit(&self, event_loop: &ActiveEventLoop) { |
| 6583 | | if let Some(state) = &self.state { |
| 6584 | | state.publish_now(QUIT_PUBLISH); |
| 6585 | | } |
| 6586 | | event_loop.exit(); |
| 6587 | | } |
| 6588 | 6581 | } |
| 6589 | 6582 | |
| 6590 | | /// How long quitting waits for the open section's edits to reach its file; they stay in the |
| 6591 | | /// replica and publish at the next launch otherwise. |
| 6583 | /// How long quitting waits for the open section's edits to reach its file and for every |
| 6584 | /// section to close; edits left stay in the replica and publish at the next launch. |
| 6592 | 6585 | #[cfg(not(target_arch = "wasm32"))] |
| 6593 | | const QUIT_PUBLISH: std::time::Duration = std::time::Duration::from_secs(3); |
| 6586 | const QUIT: std::time::Duration = std::time::Duration::from_secs(3); |
| 6594 | 6587 | |
| 6595 | 6588 | #[cfg(not(target_arch = "wasm32"))] |
| 6596 | 6589 | impl ApplicationHandler<UserEvent> for App { |
| ... | ... | @@ -6610,7 +6603,7 @@ impl ApplicationHandler<UserEvent> for App { |
| 6610 | 6603 | }; |
| 6611 | 6604 | match event { |
| 6612 | 6605 | UserEvent::Quit | UserEvent::Replay(Replay::Quit) => self.close(event_loop), |
| 6613 | | UserEvent::Exit => self.exit(event_loop), |
| 6606 | UserEvent::Exit => event_loop.exit(), |
| 6614 | 6607 | UserEvent::Renderer(chosen) | UserEvent::Replay(Replay::Renderer(chosen)) => { |
| 6615 | 6608 | let state = self.state.take().expect("The window is open"); |
| 6616 | 6609 | match state.switch_renderer(chosen) { |
| ... | ... | @@ -6831,10 +6824,37 @@ impl ApplicationHandler<UserEvent> for App { |
| 6831 | 6824 | /// Drops the window's state while the event loop still holds the Wayland connection the |
| 6832 | 6825 | /// clipboard and the surface use; `run_app` closes it on returning. |
| 6833 | 6826 | fn exiting(&mut self, _: &ActiveEventLoop) { |
| 6834 | | self.restart = self |
| 6835 | | .state |
| 6836 | | .take() |
| 6837 | | .and_then(|state| state.updates.restarting()); |
| 6827 | let Some(mut state) = self.state.take() else { |
| 6828 | return; |
| 6829 | }; |
| 6830 | let deadline = Instant::now() + QUIT; |
| 6831 | state.publish_now(QUIT); |
| 6832 | self.restart = state.updates.restarting(); |
| 6833 | let session = state.session.take(); |
| 6834 | let libraries: Vec<_> = (state.notebooks.iter()) |
| 6835 | .chain(session.as_ref().map(|session| &session.library)) |
| 6836 | .cloned() |
| 6837 | .collect(); |
| 6838 | // Dropped sections and backgrounds stop without waiting, so the process could end first. |
| 6839 | let (closed, closing) = mpsc::channel::<()>(); |
| 6840 | std::thread::spawn(move || { |
| 6841 | // Backgrounds first, or a released section would be checked again. |
| 6842 | for background in libraries |
| 6843 | .iter() |
| 6844 | .filter_map(|library| library.background.as_ref()) |
| 6845 | { |
| 6846 | background.stop(); |
| 6847 | } |
| 6848 | if let Some(session) = session |
| 6849 | && let Err(error) = session.section.close() |
| 6850 | { |
| 6851 | eprintln!("Synchronization stopped: {error}"); |
| 6852 | } |
| 6853 | libraries.iter().for_each(|library| library.close_kept()); |
| 6854 | drop(closed); |
| 6855 | }); |
| 6856 | drop(state); |
| 6857 | let _ = closing.recv_timeout(deadline.saturating_duration_since(Instant::now())); |
| 6838 | 6858 | } |
| 6839 | 6859 | } |
| 6840 | 6860 | |