Skip to content

Commit ec9818a

Browse files
refactor(core)!: App::run_iteration improvements (#8696)
* refactor(core): App::run_iteration improvements * lint * fixes * fix exit * Apply suggestions from code review Co-authored-by: Fabian-Lars <fabianlars@fabianlars.de> * update cargo.toml * booooool * fix mock runtime * fix doctests * fix doctest againrrrr --------- Co-authored-by: Fabian-Lars <fabianlars@fabianlars.de>
1 parent 9cb9aa7 commit ec9818a

File tree

13 files changed

+158
-75
lines changed

13 files changed

+158
-75
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"tauri": patch:breaking
3+
---
4+
5+
Added a callback to the `App::run_iteration` and removed its return value.

core/tauri-runtime-wry/src/lib.rs

Lines changed: 10 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ use tauri_runtime::{
2121
WindowBuilderBase, WindowEvent, WindowId,
2222
},
2323
DeviceEventFilter, Error, EventLoopProxy, ExitRequestedEventAction, Icon, Result, RunEvent,
24-
RunIteration, Runtime, RuntimeHandle, RuntimeInitArgs, UserAttentionType, UserEvent,
25-
WebviewDispatch, WindowDispatch, WindowEventId,
24+
Runtime, RuntimeHandle, RuntimeInitArgs, UserAttentionType, UserEvent, WebviewDispatch,
25+
WindowDispatch, WindowEventId,
2626
};
2727

2828
#[cfg(target_os = "macos")]
@@ -2286,7 +2286,7 @@ impl<T: UserEvent> Runtime<T> for Wry<T> {
22862286
}
22872287

22882288
#[cfg(desktop)]
2289-
fn run_iteration<F: FnMut(RunEvent<T>) + 'static>(&mut self, mut callback: F) -> RunIteration {
2289+
fn run_iteration<F: FnMut(RunEvent<T>)>(&mut self, mut callback: F) {
22902290
use tao::platform::run_return::EventLoopExtRunReturn;
22912291
let windows = self.context.main_thread.windows.clone();
22922292
let webview_id_map = self.context.webview_id_map.clone();
@@ -2296,8 +2296,6 @@ impl<T: UserEvent> Runtime<T> for Wry<T> {
22962296
#[cfg(feature = "tracing")]
22972297
let active_tracing_spans = self.context.main_thread.active_tracing_spans.clone();
22982298

2299-
let mut iteration = RunIteration::default();
2300-
23012299
let proxy = self.event_loop.create_proxy();
23022300

23032301
self
@@ -2328,7 +2326,7 @@ impl<T: UserEvent> Runtime<T> for Wry<T> {
23282326
}
23292327
}
23302328

2331-
iteration = handle_event_loop(
2329+
handle_event_loop(
23322330
event,
23332331
event_loop,
23342332
control_flow,
@@ -2341,8 +2339,6 @@ impl<T: UserEvent> Runtime<T> for Wry<T> {
23412339
},
23422340
);
23432341
});
2344-
2345-
iteration
23462342
}
23472343

23482344
fn run<F: FnMut(RunEvent<T>) + 'static>(self, mut callback: F) {
@@ -2392,7 +2388,7 @@ impl<T: UserEvent> Runtime<T> for Wry<T> {
23922388
}
23932389

23942390
pub struct EventLoopIterationContext<'a, T: UserEvent> {
2395-
pub callback: &'a mut (dyn FnMut(RunEvent<T>) + 'static),
2391+
pub callback: &'a mut (dyn FnMut(RunEvent<T>)),
23962392
pub webview_id_map: WindowIdStore,
23972393
pub windows: Rc<RefCell<HashMap<WindowId, WindowWrapper>>>,
23982394
#[cfg(feature = "tracing")]
@@ -2408,7 +2404,7 @@ fn handle_user_message<T: UserEvent>(
24082404
event_loop: &EventLoopWindowTarget<Message<T>>,
24092405
message: Message<T>,
24102406
context: UserMessageContext,
2411-
) -> RunIteration {
2407+
) {
24122408
let UserMessageContext {
24132409
webview_id_map,
24142410
windows,
@@ -2825,19 +2821,14 @@ fn handle_user_message<T: UserEvent>(
28252821

28262822
Message::UserEvent(_) => (),
28272823
}
2828-
2829-
let it = RunIteration {
2830-
window_count: windows.borrow().len(),
2831-
};
2832-
it
28332824
}
28342825

28352826
fn handle_event_loop<T: UserEvent>(
28362827
event: Event<'_, Message<T>>,
28372828
event_loop: &EventLoopWindowTarget<Message<T>>,
28382829
control_flow: &mut ControlFlow,
28392830
context: EventLoopIterationContext<'_, T>,
2840-
) -> RunIteration {
2831+
) {
28412832
let EventLoopIterationContext {
28422833
callback,
28432834
webview_id_map,
@@ -2994,7 +2985,7 @@ fn handle_event_loop<T: UserEvent>(
29942985
}
29952986
Message::UserEvent(t) => callback(RunEvent::UserEvent(t)),
29962987
message => {
2997-
return handle_user_message(
2988+
handle_user_message(
29982989
event_loop,
29992990
message,
30002991
UserMessageContext {
@@ -3010,15 +3001,10 @@ fn handle_event_loop<T: UserEvent>(
30103001
}
30113002
_ => (),
30123003
}
3013-
3014-
let it = RunIteration {
3015-
window_count: windows.borrow().len(),
3016-
};
3017-
it
30183004
}
30193005

3020-
fn on_close_requested<'a, T: UserEvent>(
3021-
callback: &'a mut (dyn FnMut(RunEvent<T>) + 'static),
3006+
fn on_close_requested<T: UserEvent>(
3007+
callback: &mut (dyn FnMut(RunEvent<T>)),
30223008
window_id: WindowId,
30233009
windows: Rc<RefCell<HashMap<WindowId, WindowWrapper>>>,
30243010
) {

core/tauri-runtime/src/lib.rs

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -184,12 +184,6 @@ pub enum ExitRequestedEventAction {
184184
Prevent,
185185
}
186186

187-
/// Metadata for a runtime event loop iteration on `run_iteration`.
188-
#[derive(Debug, Clone, Default)]
189-
pub struct RunIteration {
190-
pub window_count: usize,
191-
}
192-
193187
/// Application's activation policy. Corresponds to NSApplicationActivationPolicy.
194188
#[cfg(target_os = "macos")]
195189
#[cfg_attr(docsrs, doc(cfg(target_os = "macos")))]
@@ -340,9 +334,9 @@ pub trait Runtime<T: UserEvent>: Debug + Sized + 'static {
340334
/// [`tao`]: https://crates.io/crates/tao
341335
fn set_device_event_filter(&mut self, filter: DeviceEventFilter);
342336

343-
/// Runs the one step of the webview runtime event loop and returns control flow to the caller.
337+
/// Runs an iteration of the runtime event loop and returns control flow to the caller.
344338
#[cfg(desktop)]
345-
fn run_iteration<F: Fn(RunEvent<T>) + 'static>(&mut self, callback: F) -> RunIteration;
339+
fn run_iteration<F: FnMut(RunEvent<T>)>(&mut self, callback: F);
346340

347341
/// Run the webview runtime.
348342
fn run<F: FnMut(RunEvent<T>) + 'static>(self, callback: F);

core/tauri/Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,3 +205,7 @@ path = "../../examples/streaming/main.rs"
205205
name = "isolation"
206206
path = "../../examples/isolation/main.rs"
207207
required-features = [ "isolation" ]
208+
209+
[[example]]
210+
name = "run-iteration"
211+
path = "../../examples/run-iteration/main.rs"

core/tauri/src/app.rs

Lines changed: 30 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -406,6 +406,7 @@ pub struct App<R: Runtime> {
406406
setup: Option<SetupHook<R>>,
407407
manager: Arc<AppManager<R>>,
408408
handle: AppHandle<R>,
409+
ran_setup: bool,
409410
}
410411

411412
impl<R: Runtime> fmt::Debug for App<R> {
@@ -862,59 +863,57 @@ impl<R: Runtime> App<R> {
862863
if let Err(e) = setup(&mut self) {
863864
panic!("Failed to setup app: {e}");
864865
}
865-
on_event_loop_event(
866-
&app_handle,
867-
RuntimeRunEvent::Ready,
868-
&manager,
869-
Some(&mut callback),
870-
);
866+
let event = on_event_loop_event(&app_handle, RuntimeRunEvent::Ready, &manager);
867+
callback(&app_handle, event);
871868
}
872869
RuntimeRunEvent::Exit => {
873-
on_event_loop_event(
874-
&app_handle,
875-
RuntimeRunEvent::Exit,
876-
&manager,
877-
Some(&mut callback),
878-
);
870+
let event = on_event_loop_event(&app_handle, RuntimeRunEvent::Exit, &manager);
871+
callback(&app_handle, event);
879872
app_handle.cleanup_before_exit();
880873
}
881874
_ => {
882-
on_event_loop_event(&app_handle, event, &manager, Some(&mut callback));
875+
let event = on_event_loop_event(&app_handle, event, &manager);
876+
callback(&app_handle, event);
883877
}
884878
});
885879
}
886880

887-
/// Runs a iteration of the runtime event loop and immediately return.
881+
/// Runs an iteration of the runtime event loop and immediately return.
888882
///
889883
/// Note that when using this API, app cleanup is not automatically done.
890884
/// The cleanup calls [`App::cleanup_before_exit`] so you may want to call that function before exiting the application.
891885
///
892886
/// # Examples
893887
/// ```no_run
888+
/// use tauri::Manager;
889+
///
894890
/// let mut app = tauri::Builder::default()
895891
/// // on an actual app, remove the string argument
896892
/// .build(tauri::generate_context!("test/fixture/src-tauri/tauri.conf.json"))
897893
/// .expect("error while building tauri application");
894+
///
898895
/// loop {
899-
/// let iteration = app.run_iteration();
900-
/// if iteration.window_count == 0 {
896+
/// app.run_iteration(|_app, _event| {});
897+
/// if app.webview_windows().is_empty() {
901898
/// app.cleanup_before_exit();
902899
/// break;
903900
/// }
904901
/// }
905902
/// ```
906903
#[cfg(desktop)]
907-
#[cfg_attr(feature = "tracing", tracing::instrument(name = "app::run_iteration"))]
908-
pub fn run_iteration(&mut self) -> crate::runtime::RunIteration {
904+
pub fn run_iteration<F: FnMut(&AppHandle<R>, RunEvent)>(&mut self, mut callback: F) {
909905
let manager = self.manager.clone();
910906
let app_handle = self.handle().clone();
907+
908+
if !self.ran_setup {
909+
if let Err(e) = setup(self) {
910+
panic!("Failed to setup app: {e}");
911+
}
912+
}
913+
911914
self.runtime.as_mut().unwrap().run_iteration(move |event| {
912-
on_event_loop_event(
913-
&app_handle,
914-
event,
915-
&manager,
916-
Option::<&mut Box<dyn FnMut(&AppHandle<R>, RunEvent)>>::None,
917-
)
915+
let event = on_event_loop_event(&app_handle, event, &manager);
916+
callback(&app_handle, event);
918917
})
919918
}
920919
}
@@ -1537,6 +1536,7 @@ tauri::Builder::default()
15371536
runtime_handle,
15381537
manager,
15391538
},
1539+
ran_setup: false,
15401540
};
15411541

15421542
#[cfg(desktop)]
@@ -1674,6 +1674,8 @@ unsafe impl<R: Runtime> HasRawDisplayHandle for App<R> {
16741674

16751675
#[cfg_attr(feature = "tracing", tracing::instrument(name = "app::setup"))]
16761676
fn setup<R: Runtime>(app: &mut App<R>) -> crate::Result<()> {
1677+
app.ran_setup = true;
1678+
16771679
let window_labels = app
16781680
.config()
16791681
.tauri
@@ -1701,19 +1703,17 @@ fn setup<R: Runtime>(app: &mut App<R>) -> crate::Result<()> {
17011703
Ok(())
17021704
}
17031705

1704-
fn on_event_loop_event<R: Runtime, F: FnMut(&AppHandle<R>, RunEvent) + 'static>(
1706+
fn on_event_loop_event<R: Runtime>(
17051707
app_handle: &AppHandle<R>,
17061708
event: RuntimeRunEvent<EventLoopMessage>,
17071709
manager: &AppManager<R>,
1708-
callback: Option<&mut F>,
1709-
) {
1710+
) -> RunEvent {
17101711
if let RuntimeRunEvent::WindowEvent {
17111712
label,
17121713
event: RuntimeWindowEvent::Destroyed,
17131714
} = &event
17141715
{
1715-
// TODO: destroy webviews
1716-
manager.window.on_window_close(label);
1716+
manager.on_window_close(label);
17171717
}
17181718

17191719
let event = match event {
@@ -1805,9 +1805,7 @@ fn on_event_loop_event<R: Runtime, F: FnMut(&AppHandle<R>, RunEvent) + 'static>(
18051805
.expect("poisoned plugin store")
18061806
.on_event(app_handle, &event);
18071807

1808-
if let Some(c) = callback {
1809-
c(app_handle, event);
1810-
}
1808+
event
18111809
}
18121810

18131811
#[cfg(test)]

core/tauri/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,7 @@ pub use {
214214
dpi::{LogicalPosition, LogicalSize, PhysicalPosition, PhysicalSize, Pixel, Position, Size},
215215
CursorIcon, FileDropEvent,
216216
},
217-
DeviceEventFilter, RunIteration, UserAttentionType,
217+
DeviceEventFilter, UserAttentionType,
218218
},
219219
self::state::{State, StateManager},
220220
self::utils::{

core/tauri/src/manager/mod.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -542,6 +542,14 @@ impl<R: Runtime> AppManager<R> {
542542
.map(|w| w.1.clone())
543543
}
544544

545+
pub(crate) fn on_window_close(&self, label: &str) {
546+
if let Some(window) = self.window.windows_lock().remove(label) {
547+
for webview in window.webviews() {
548+
self.webview.webviews_lock().remove(webview.label());
549+
}
550+
}
551+
}
552+
545553
pub fn windows(&self) -> HashMap<String, Window<R>> {
546554
self.window.windows_lock().clone()
547555
}

core/tauri/src/manager/window.rs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -125,10 +125,6 @@ impl<R: Runtime> WindowManager<R> {
125125
window
126126
}
127127

128-
pub(crate) fn on_window_close(&self, label: &str) {
129-
self.windows_lock().remove(label);
130-
}
131-
132128
pub fn labels(&self) -> HashSet<String> {
133129
self.windows_lock().keys().cloned().collect()
134130
}

core/tauri/src/test/mock_runtime.rs

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -992,12 +992,7 @@ impl<T: UserEvent> Runtime<T> for MockRuntime {
992992
target_os = "netbsd",
993993
target_os = "openbsd"
994994
))]
995-
fn run_iteration<F: Fn(RunEvent<T>) + 'static>(
996-
&mut self,
997-
callback: F,
998-
) -> tauri_runtime::RunIteration {
999-
Default::default()
1000-
}
995+
fn run_iteration<F: FnMut(RunEvent<T>)>(&mut self, callback: F) {}
1001996

1002997
fn run<F: FnMut(RunEvent<T>) + 'static>(self, mut callback: F) {
1003998
self.is_running.store(true, Ordering::Relaxed);

examples/run-iteration/README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Run Iteration Example
2+
3+
To execute run the following on the root directory of the repository: `cargo run --example run-iteration`.

0 commit comments

Comments
 (0)