Skip to content

Commit b4622ea

Browse files
authored
refactor(app): run setup and window creation when event loop is ready (#4914)
1 parent 6119f45 commit b4622ea

File tree

4 files changed

+86
-29
lines changed

4 files changed

+86
-29
lines changed

.changes/config.json

-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
"timeout": 3600000,
44
"pkgManagers": {
55
"rust": {
6-
"errorOnVersionRange": "^2.0.0-0",
76
"version": true,
87
"getPublishedVersion": "cargo search ${ pkgFile.pkg.package.name } --limit 1 | sed -nE \"s/^[^\\\"]*\\\"//; s/\\\".*//1p\"",
98
"prepublish": [
@@ -78,7 +77,6 @@
7877
]
7978
},
8079
"javascript": {
81-
"errorOnVersionRange": "^2.0.0-0",
8280
"version": true,
8381
"getPublishedVersion": "npm view ${ pkgFile.pkg.name } version",
8482
"prepublish": [

.changes/refactor-setup.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"tauri": major
3+
---
4+
5+
**Breaking change:** The window creation and setup hook are now called when the event loop is ready.

core/tauri/src/app.rs

+70-22
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ use tauri_utils::PackageInfo;
4040

4141
use std::{
4242
collections::HashMap,
43+
fmt,
4344
path::{Path, PathBuf},
4445
sync::{mpsc::Sender, Arc, Weak},
4546
};
@@ -526,9 +527,10 @@ impl<R: Runtime> ManagerBase<R> for AppHandle<R> {
526527
///
527528
/// This type implements [`Manager`] which allows for manipulation of global application items.
528529
#[default_runtime(crate::Wry, wry)]
529-
#[derive(Debug)]
530530
pub struct App<R: Runtime> {
531531
runtime: Option<R>,
532+
pending_windows: Option<Vec<PendingWindow<EventLoopMessage, R>>>,
533+
setup: Option<SetupHook<R>>,
532534
manager: WindowManager<R>,
533535
#[cfg(all(desktop, feature = "global-shortcut"))]
534536
global_shortcut_manager: R::GlobalShortcutManager,
@@ -537,14 +539,34 @@ pub struct App<R: Runtime> {
537539
handle: AppHandle<R>,
538540
}
539541

542+
impl<R: Runtime> fmt::Debug for App<R> {
543+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
544+
let mut d = f.debug_struct("App");
545+
d.field("runtime", &self.runtime)
546+
.field("manager", &self.manager)
547+
.field("handle", &self.handle);
548+
549+
#[cfg(all(desktop, feature = "global-shortcut"))]
550+
d.field("global_shortcut_manager", &self.global_shortcut_manager);
551+
#[cfg(feature = "clipboard")]
552+
d.field("clipboard_manager", &self.clipboard_manager);
553+
554+
d.finish()
555+
}
556+
}
557+
540558
impl<R: Runtime> Manager<R> for App<R> {}
541559
impl<R: Runtime> ManagerBase<R> for App<R> {
542560
fn manager(&self) -> &WindowManager<R> {
543561
&self.manager
544562
}
545563

546564
fn runtime(&self) -> RuntimeOrDispatch<'_, R> {
547-
RuntimeOrDispatch::Runtime(self.runtime.as_ref().unwrap())
565+
if let Some(runtime) = self.runtime.as_ref() {
566+
RuntimeOrDispatch::Runtime(runtime)
567+
} else {
568+
self.handle.runtime()
569+
}
548570
}
549571

550572
fn managed_app_handle(&self) -> AppHandle<R> {
@@ -775,6 +797,17 @@ impl<R: Runtime> App<R> {
775797
let app_handle = self.handle();
776798
let manager = self.manager.clone();
777799
self.runtime.take().unwrap().run(move |event| match event {
800+
RuntimeRunEvent::Ready => {
801+
if let Err(e) = setup(&mut self) {
802+
panic!("Failed to setup app: {}", e);
803+
}
804+
on_event_loop_event(
805+
&app_handle,
806+
RuntimeRunEvent::Ready,
807+
&manager,
808+
Some(&mut callback),
809+
);
810+
}
778811
RuntimeRunEvent::Exit => {
779812
on_event_loop_event(
780813
&app_handle,
@@ -1460,8 +1493,11 @@ impl<R: Runtime> Builder<R> {
14601493
#[cfg(feature = "clipboard")]
14611494
let clipboard_manager = runtime.clipboard_manager();
14621495

1496+
#[allow(unused_mut)]
14631497
let mut app = App {
14641498
runtime: Some(runtime),
1499+
pending_windows: Some(self.pending_windows),
1500+
setup: Some(self.setup),
14651501
manager: manager.clone(),
14661502
#[cfg(all(desktop, feature = "global-shortcut"))]
14671503
global_shortcut_manager: global_shortcut_manager.clone(),
@@ -1551,26 +1587,6 @@ impl<R: Runtime> Builder<R> {
15511587

15521588
app.manager.initialize_plugins(&app.handle())?;
15531589

1554-
let window_labels = self
1555-
.pending_windows
1556-
.iter()
1557-
.map(|p| p.label.clone())
1558-
.collect::<Vec<_>>();
1559-
1560-
for pending in self.pending_windows {
1561-
let pending =
1562-
app
1563-
.manager
1564-
.prepare_window(app.handle.clone(), pending, &window_labels, None)?;
1565-
let detached = app.runtime.as_ref().unwrap().create_window(pending)?;
1566-
let _window = app.manager.attach_window(app.handle(), detached);
1567-
}
1568-
1569-
(self.setup)(&mut app).map_err(|e| crate::Error::Setup(e.into()))?;
1570-
1571-
#[cfg(updater)]
1572-
app.run_updater();
1573-
15741590
Ok(app)
15751591
}
15761592

@@ -1593,6 +1609,38 @@ unsafe impl HasRawDisplayHandle for App {
15931609
}
15941610
}
15951611

1612+
fn setup<R: Runtime>(app: &mut App<R>) -> crate::Result<()> {
1613+
let pending_windows = app.pending_windows.take();
1614+
if let Some(pending_windows) = pending_windows {
1615+
let window_labels = pending_windows
1616+
.iter()
1617+
.map(|p| p.label.clone())
1618+
.collect::<Vec<_>>();
1619+
1620+
for pending in pending_windows {
1621+
let pending =
1622+
app
1623+
.manager
1624+
.prepare_window(app.handle.clone(), pending, &window_labels, None)?;
1625+
let detached = if let RuntimeOrDispatch::RuntimeHandle(runtime) = app.handle().runtime() {
1626+
runtime.create_window(pending)?
1627+
} else {
1628+
// the AppHandle's runtime is always RuntimeOrDispatch::RuntimeHandle
1629+
unreachable!()
1630+
};
1631+
let _window = app.manager.attach_window(app.handle(), detached);
1632+
}
1633+
}
1634+
1635+
if let Some(setup) = app.setup.take() {
1636+
(setup)(app).map_err(|e| crate::Error::Setup(e.into()))?;
1637+
}
1638+
1639+
#[cfg(updater)]
1640+
app.run_updater();
1641+
Ok(())
1642+
}
1643+
15961644
fn on_event_loop_event<R: Runtime, F: FnMut(&AppHandle<R>, RunEvent) + 'static>(
15971645
app_handle: &AppHandle<R>,
15981646
event: RuntimeRunEvent<EventLoopMessage>,

core/tauri/src/test/mod.rs

+11-5
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,10 @@ use std::{borrow::Cow, sync::Arc};
1313

1414
#[cfg(shell_scope)]
1515
use crate::ShellScopeConfig;
16-
use crate::{Manager, Pattern};
16+
use crate::{Manager, Pattern, WindowBuilder};
1717
use tauri_utils::{
1818
assets::{AssetKey, Assets, CspHash},
19-
config::{CliConfig, Config, PatternKind, TauriConfig},
19+
config::{CliConfig, Config, PatternKind, TauriConfig, WindowUrl},
2020
};
2121

2222
pub struct NoopAsset {
@@ -46,7 +46,7 @@ pub fn mock_context<A: Assets>(assets: A) -> crate::Context<A> {
4646
package: Default::default(),
4747
tauri: TauriConfig {
4848
pattern: PatternKind::Brownfield,
49-
windows: vec![Default::default()],
49+
windows: Vec::new(),
5050
cli: Some(CliConfig {
5151
description: None,
5252
long_description: None,
@@ -86,9 +86,15 @@ pub fn mock_context<A: Assets>(assets: A) -> crate::Context<A> {
8686
}
8787

8888
pub fn mock_app() -> crate::App<MockRuntime> {
89-
crate::Builder::<MockRuntime>::new()
89+
let app = crate::Builder::<MockRuntime>::new()
9090
.build(mock_context(noop_assets()))
91-
.unwrap()
91+
.unwrap();
92+
93+
WindowBuilder::new(&app, "main", WindowUrl::App("index.html".into()))
94+
.build()
95+
.unwrap();
96+
97+
app
9298
}
9399

94100
pub(crate) fn mock_invoke_context() -> crate::endpoints::InvokeContext<MockRuntime> {

0 commit comments

Comments
 (0)