Skip to content

Commit

Permalink
refactor(app): run setup and window creation when event loop is ready (
Browse files Browse the repository at this point in the history
  • Loading branch information
lucasfernog committed Aug 11, 2022
1 parent 6119f45 commit b4622ea
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 29 deletions.
2 changes: 0 additions & 2 deletions .changes/config.json
Expand Up @@ -3,7 +3,6 @@
"timeout": 3600000,
"pkgManagers": {
"rust": {
"errorOnVersionRange": "^2.0.0-0",
"version": true,
"getPublishedVersion": "cargo search ${ pkgFile.pkg.package.name } --limit 1 | sed -nE \"s/^[^\\\"]*\\\"//; s/\\\".*//1p\"",
"prepublish": [
Expand Down Expand Up @@ -78,7 +77,6 @@
]
},
"javascript": {
"errorOnVersionRange": "^2.0.0-0",
"version": true,
"getPublishedVersion": "npm view ${ pkgFile.pkg.name } version",
"prepublish": [
Expand Down
5 changes: 5 additions & 0 deletions .changes/refactor-setup.md
@@ -0,0 +1,5 @@
---
"tauri": major
---

**Breaking change:** The window creation and setup hook are now called when the event loop is ready.
92 changes: 70 additions & 22 deletions core/tauri/src/app.rs
Expand Up @@ -40,6 +40,7 @@ use tauri_utils::PackageInfo;

use std::{
collections::HashMap,
fmt,
path::{Path, PathBuf},
sync::{mpsc::Sender, Arc, Weak},
};
Expand Down Expand Up @@ -526,9 +527,10 @@ impl<R: Runtime> ManagerBase<R> for AppHandle<R> {
///
/// This type implements [`Manager`] which allows for manipulation of global application items.
#[default_runtime(crate::Wry, wry)]
#[derive(Debug)]
pub struct App<R: Runtime> {
runtime: Option<R>,
pending_windows: Option<Vec<PendingWindow<EventLoopMessage, R>>>,
setup: Option<SetupHook<R>>,
manager: WindowManager<R>,
#[cfg(all(desktop, feature = "global-shortcut"))]
global_shortcut_manager: R::GlobalShortcutManager,
Expand All @@ -537,14 +539,34 @@ pub struct App<R: Runtime> {
handle: AppHandle<R>,
}

impl<R: Runtime> fmt::Debug for App<R> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut d = f.debug_struct("App");
d.field("runtime", &self.runtime)
.field("manager", &self.manager)
.field("handle", &self.handle);

#[cfg(all(desktop, feature = "global-shortcut"))]
d.field("global_shortcut_manager", &self.global_shortcut_manager);
#[cfg(feature = "clipboard")]
d.field("clipboard_manager", &self.clipboard_manager);

d.finish()
}
}

impl<R: Runtime> Manager<R> for App<R> {}
impl<R: Runtime> ManagerBase<R> for App<R> {
fn manager(&self) -> &WindowManager<R> {
&self.manager
}

fn runtime(&self) -> RuntimeOrDispatch<'_, R> {
RuntimeOrDispatch::Runtime(self.runtime.as_ref().unwrap())
if let Some(runtime) = self.runtime.as_ref() {
RuntimeOrDispatch::Runtime(runtime)
} else {
self.handle.runtime()
}
}

fn managed_app_handle(&self) -> AppHandle<R> {
Expand Down Expand Up @@ -775,6 +797,17 @@ impl<R: Runtime> App<R> {
let app_handle = self.handle();
let manager = self.manager.clone();
self.runtime.take().unwrap().run(move |event| match event {
RuntimeRunEvent::Ready => {
if let Err(e) = setup(&mut self) {
panic!("Failed to setup app: {}", e);
}
on_event_loop_event(
&app_handle,
RuntimeRunEvent::Ready,
&manager,
Some(&mut callback),
);
}
RuntimeRunEvent::Exit => {
on_event_loop_event(
&app_handle,
Expand Down Expand Up @@ -1460,8 +1493,11 @@ impl<R: Runtime> Builder<R> {
#[cfg(feature = "clipboard")]
let clipboard_manager = runtime.clipboard_manager();

#[allow(unused_mut)]
let mut app = App {
runtime: Some(runtime),
pending_windows: Some(self.pending_windows),
setup: Some(self.setup),
manager: manager.clone(),
#[cfg(all(desktop, feature = "global-shortcut"))]
global_shortcut_manager: global_shortcut_manager.clone(),
Expand Down Expand Up @@ -1551,26 +1587,6 @@ impl<R: Runtime> Builder<R> {

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

let window_labels = self
.pending_windows
.iter()
.map(|p| p.label.clone())
.collect::<Vec<_>>();

for pending in self.pending_windows {
let pending =
app
.manager
.prepare_window(app.handle.clone(), pending, &window_labels, None)?;
let detached = app.runtime.as_ref().unwrap().create_window(pending)?;
let _window = app.manager.attach_window(app.handle(), detached);
}

(self.setup)(&mut app).map_err(|e| crate::Error::Setup(e.into()))?;

#[cfg(updater)]
app.run_updater();

Ok(app)
}

Expand All @@ -1593,6 +1609,38 @@ unsafe impl HasRawDisplayHandle for App {
}
}

fn setup<R: Runtime>(app: &mut App<R>) -> crate::Result<()> {
let pending_windows = app.pending_windows.take();
if let Some(pending_windows) = pending_windows {
let window_labels = pending_windows
.iter()
.map(|p| p.label.clone())
.collect::<Vec<_>>();

for pending in pending_windows {
let pending =
app
.manager
.prepare_window(app.handle.clone(), pending, &window_labels, None)?;
let detached = if let RuntimeOrDispatch::RuntimeHandle(runtime) = app.handle().runtime() {
runtime.create_window(pending)?
} else {
// the AppHandle's runtime is always RuntimeOrDispatch::RuntimeHandle
unreachable!()
};
let _window = app.manager.attach_window(app.handle(), detached);
}
}

if let Some(setup) = app.setup.take() {
(setup)(app).map_err(|e| crate::Error::Setup(e.into()))?;
}

#[cfg(updater)]
app.run_updater();
Ok(())
}

fn on_event_loop_event<R: Runtime, F: FnMut(&AppHandle<R>, RunEvent) + 'static>(
app_handle: &AppHandle<R>,
event: RuntimeRunEvent<EventLoopMessage>,
Expand Down
16 changes: 11 additions & 5 deletions core/tauri/src/test/mod.rs
Expand Up @@ -13,10 +13,10 @@ use std::{borrow::Cow, sync::Arc};

#[cfg(shell_scope)]
use crate::ShellScopeConfig;
use crate::{Manager, Pattern};
use crate::{Manager, Pattern, WindowBuilder};
use tauri_utils::{
assets::{AssetKey, Assets, CspHash},
config::{CliConfig, Config, PatternKind, TauriConfig},
config::{CliConfig, Config, PatternKind, TauriConfig, WindowUrl},
};

pub struct NoopAsset {
Expand Down Expand Up @@ -46,7 +46,7 @@ pub fn mock_context<A: Assets>(assets: A) -> crate::Context<A> {
package: Default::default(),
tauri: TauriConfig {
pattern: PatternKind::Brownfield,
windows: vec![Default::default()],
windows: Vec::new(),
cli: Some(CliConfig {
description: None,
long_description: None,
Expand Down Expand Up @@ -86,9 +86,15 @@ pub fn mock_context<A: Assets>(assets: A) -> crate::Context<A> {
}

pub fn mock_app() -> crate::App<MockRuntime> {
crate::Builder::<MockRuntime>::new()
let app = crate::Builder::<MockRuntime>::new()
.build(mock_context(noop_assets()))
.unwrap()
.unwrap();

WindowBuilder::new(&app, "main", WindowUrl::App("index.html".into()))
.build()
.unwrap();

app
}

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

0 comments on commit b4622ea

Please sign in to comment.