Skip to content

Commit 50ffdc0

Browse files
authored
feat(core): panic when a dispatcher getter is used on the main thread (#2455)
1 parent c76f4b7 commit 50ffdc0

File tree

5 files changed

+109
-55
lines changed

5 files changed

+109
-55
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
"tauri": patch
3+
"tauri-runtime": patch
4+
"tauri-runtime-wry": patch
5+
---
6+
7+
Panic when a dispatcher getter method (`Window`, `GlobalShortcutHandle`, `ClipboardManager` and `MenuHandle` APIs) is called on the main thread.

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

+10-8
Original file line numberDiff line numberDiff line change
@@ -112,10 +112,11 @@ pub type WindowMenuEventListeners = Arc<Mutex<HashMap<Uuid, MenuEventHandler>>>;
112112

113113
macro_rules! dispatcher_getter {
114114
($self: ident, $message: expr) => {{
115-
if current_thread().id() == $self.context.main_thread_id
116-
&& !$self.context.is_event_loop_running.load(Ordering::Relaxed)
117-
{
118-
panic!("This API cannot be called when the event loop is not running");
115+
if current_thread().id() == $self.context.main_thread_id {
116+
panic!("This API cannot be called on the main thread. Try using `std::thread::spawn` or `tauri::async_runtime::spawn`.");
117+
}
118+
if !$self.context.is_event_loop_running.load(Ordering::Relaxed) {
119+
panic!("This API cannot be called when the event loop is not running. Try using `std::thread::spawn` or `tauri::async_runtime::spawn`.");
119120
}
120121
let (tx, rx) = channel();
121122
$self
@@ -129,10 +130,11 @@ macro_rules! dispatcher_getter {
129130

130131
macro_rules! getter {
131132
($self: ident, $rx: expr, $message: expr) => {{
132-
if current_thread().id() == $self.context.main_thread_id
133-
&& !$self.context.is_event_loop_running.load(Ordering::Relaxed)
134-
{
135-
panic!("This API cannot be called when the event loop is not running");
133+
if current_thread().id() == $self.context.main_thread_id {
134+
panic!("This API cannot be called on the main thread. Try using `std::thread::spawn` or `tauri::async_runtime::spawn`.");
135+
}
136+
if !$self.context.is_event_loop_running.load(Ordering::Relaxed) {
137+
panic!("This API cannot be called when the event loop is not running. Try using `std::thread::spawn` or `tauri::async_runtime::spawn`.");
136138
}
137139
$self
138140
.context

core/tauri-runtime/src/lib.rs

+24-13
Original file line numberDiff line numberDiff line change
@@ -258,16 +258,20 @@ pub trait GlobalShortcutManager: Debug {
258258
///
259259
/// # Panics
260260
///
261-
/// Panics if the app is not running yet, usually when called on the `tauri::Builder#setup` closure.
262-
/// You can spawn a task to use the API using the `tauri::async_runtime` to prevent the panic.
261+
/// - Panics if the event loop is not running yet, usually when called on the `tauri::Builder#setup` closure.
262+
/// - Panics when called on the main thread, usually on the `tauri::App#run`closure.
263+
///
264+
/// You can spawn a task to use the API using `tauri::async_runtime::spawn` or [`std::thread::spawn`] to prevent the panic.
263265
fn is_registered(&self, accelerator: &str) -> crate::Result<bool>;
264266

265267
/// Register a global shortcut of `accelerator`.
266268
///
267269
/// # Panics
268270
///
269-
/// Panics if the app is not running yet, usually when called on the `tauri::Builder#setup` closure.
270-
/// You can spawn a task to use the API using the `tauri::async_runtime` to prevent the panic.
271+
/// - Panics if the event loop is not running yet, usually when called on the `tauri::Builder#setup` closure.
272+
/// - Panics when called on the main thread, usually on the `tauri::App#run`closure.
273+
///
274+
/// You can spawn a task to use the API using `tauri::async_runtime::spawn` or [`std::thread::spawn`] to prevent the panic.
271275
fn register<F: Fn() + Send + 'static>(
272276
&mut self,
273277
accelerator: &str,
@@ -278,16 +282,20 @@ pub trait GlobalShortcutManager: Debug {
278282
///
279283
/// # Panics
280284
///
281-
/// Panics if the app is not running yet, usually when called on the `tauri::Builder#setup` closure.
282-
/// You can spawn a task to use the API using the `tauri::async_runtime` to prevent the panic.
285+
/// - Panics if the event loop is not running yet, usually when called on the `tauri::Builder#setup` closure.
286+
/// - Panics when called on the main thread, usually on the `tauri::App#run`closure.
287+
///
288+
/// You can spawn a task to use the API using `tauri::async_runtime::spawn` or [`std::thread::spawn`] to prevent the panic.
283289
fn unregister_all(&mut self) -> crate::Result<()>;
284290

285291
/// Unregister the provided `accelerator`.
286292
///
287293
/// # Panics
288294
///
289-
/// Panics if the app is not running yet, usually when called on the `tauri::Builder#setup` closure.
290-
/// You can spawn a task to use the API using the `tauri::async_runtime` to prevent the panic.
295+
/// - Panics if the event loop is not running yet, usually when called on the `tauri::Builder#setup` closure.
296+
/// - Panics when called on the main thread, usually on the `tauri::App#run`closure.
297+
///
298+
/// You can spawn a task to use the API using `tauri::async_runtime::spawn` or [`std::thread::spawn`] to prevent the panic.
291299
fn unregister(&mut self, accelerator: &str) -> crate::Result<()>;
292300
}
293301

@@ -297,16 +305,19 @@ pub trait ClipboardManager: Debug {
297305
///
298306
/// # Panics
299307
///
300-
/// Panics if the app is not running yet, usually when called on the `tauri::Builder#setup` closure.
301-
/// You can spawn a task to use the API using the `tauri::async_runtime` to prevent the panic.
302-
308+
/// - Panics if the event loop is not running yet, usually when called on the `tauri::Builder#setup` closure.
309+
/// - Panics when called on the main thread, usually on the `tauri::App#run`closure.
310+
///
311+
/// You can spawn a task to use the API using `tauri::async_runtime::spawn` or [`std::thread::spawn`] to prevent the panic.
303312
fn write_text<T: Into<String>>(&mut self, text: T) -> Result<()>;
304313
/// Read the content in the clipboard as plain text.
305314
///
306315
/// # Panics
307316
///
308-
/// Panics if the app is not running yet, usually when called on the `tauri::Builder#setup` closure.
309-
/// You can spawn a task to use the API using the `tauri::async_runtime` to prevent the panic.
317+
/// - Panics if the event loop is not running yet, usually when called on the `tauri::Builder#setup` closure.
318+
/// - Panics when called on the main thread, usually on the `tauri::App#run`closure.
319+
///
320+
/// You can spawn a task to use the API using `tauri::async_runtime::spawn` or [`std::thread::spawn`] to prevent the panic.
310321
fn read_text(&self) -> Result<Option<String>>;
311322
}
312323

core/tauri/src/window.rs

+60-30
Original file line numberDiff line numberDiff line change
@@ -313,8 +313,10 @@ impl<R: Runtime> Window<R> {
313313
///
314314
/// # Panics
315315
///
316-
/// Panics if the app is not running yet, usually when called on the [`setup`](crate::Builder#method.setup) closure.
317-
/// You can spawn a task to use the API using the [`async_runtime`](crate::async_runtime) to prevent the panic.
316+
/// - Panics if the event loop is not running yet, usually when called on the [`setup`](crate::Builder#method.setup) closure.
317+
/// - Panics when called on the main thread, usually on the [`run`](crate::App#method.run) closure.
318+
///
319+
/// You can spawn a task to use the API using [`crate::async_runtime::spawn`] or [`std::thread::spawn`] to prevent the panic.
318320
pub fn scale_factor(&self) -> crate::Result<f64> {
319321
self.window.dispatcher.scale_factor().map_err(Into::into)
320322
}
@@ -323,8 +325,10 @@ impl<R: Runtime> Window<R> {
323325
///
324326
/// # Panics
325327
///
326-
/// Panics if the app is not running yet, usually when called on the [`setup`](crate::Builder#method.setup) closure.
327-
/// You can spawn a task to use the API using the [`async_runtime`](crate::async_runtime) to prevent the panic.
328+
/// - Panics if the event loop is not running yet, usually when called on the [`setup`](crate::Builder#method.setup) closure.
329+
/// - Panics when called on the main thread, usually on the [`run`](crate::App#method.run) closure.
330+
///
331+
/// You can spawn a task to use the API using [`crate::async_runtime::spawn`] or [`std::thread::spawn`] to prevent the panic.
328332
pub fn inner_position(&self) -> crate::Result<PhysicalPosition<i32>> {
329333
self.window.dispatcher.inner_position().map_err(Into::into)
330334
}
@@ -333,8 +337,10 @@ impl<R: Runtime> Window<R> {
333337
///
334338
/// # Panics
335339
///
336-
/// Panics if the app is not running yet, usually when called on the [`setup`](crate::Builder#method.setup) closure.
337-
/// You can spawn a task to use the API using the [`async_runtime`](crate::async_runtime) to prevent the panic.
340+
/// - Panics if the event loop is not running yet, usually when called on the [`setup`](crate::Builder#method.setup) closure.
341+
/// - Panics when called on the main thread, usually on the [`run`](crate::App#method.run) closure.
342+
///
343+
/// You can spawn a task to use the API using [`crate::async_runtime::spawn`] or [`std::thread::spawn`] to prevent the panic.
338344
pub fn outer_position(&self) -> crate::Result<PhysicalPosition<i32>> {
339345
self.window.dispatcher.outer_position().map_err(Into::into)
340346
}
@@ -345,8 +351,10 @@ impl<R: Runtime> Window<R> {
345351
///
346352
/// # Panics
347353
///
348-
/// Panics if the app is not running yet, usually when called on the [`setup`](crate::Builder#method.setup) closure.
349-
/// You can spawn a task to use the API using the [`async_runtime`](crate::async_runtime) to prevent the panic.
354+
/// - Panics if the event loop is not running yet, usually when called on the [`setup`](crate::Builder#method.setup) closure.
355+
/// - Panics when called on the main thread, usually on the [`run`](crate::App#method.run) closure.
356+
///
357+
/// You can spawn a task to use the API using [`crate::async_runtime::spawn`] or [`std::thread::spawn`] to prevent the panic.
350358
pub fn inner_size(&self) -> crate::Result<PhysicalSize<u32>> {
351359
self.window.dispatcher.inner_size().map_err(Into::into)
352360
}
@@ -357,8 +365,10 @@ impl<R: Runtime> Window<R> {
357365
///
358366
/// # Panics
359367
///
360-
/// Panics if the app is not running yet, usually when called on the [`setup`](crate::Builder#method.setup) closure.
361-
/// You can spawn a task to use the API using the [`async_runtime`](crate::async_runtime) to prevent the panic.
368+
/// - Panics if the event loop is not running yet, usually when called on the [`setup`](crate::Builder#method.setup) closure.
369+
/// - Panics when called on the main thread, usually on the [`run`](crate::App#method.run) closure.
370+
///
371+
/// You can spawn a task to use the API using [`crate::async_runtime::spawn`] or [`std::thread::spawn`] to prevent the panic.
362372
pub fn outer_size(&self) -> crate::Result<PhysicalSize<u32>> {
363373
self.window.dispatcher.outer_size().map_err(Into::into)
364374
}
@@ -367,8 +377,10 @@ impl<R: Runtime> Window<R> {
367377
///
368378
/// # Panics
369379
///
370-
/// Panics if the app is not running yet, usually when called on the [`setup`](crate::Builder#method.setup) closure.
371-
/// You can spawn a task to use the API using the [`async_runtime`](crate::async_runtime) to prevent the panic.
380+
/// - Panics if the event loop is not running yet, usually when called on the [`setup`](crate::Builder#method.setup) closure.
381+
/// - Panics when called on the main thread, usually on the [`run`](crate::App#method.run) closure.
382+
///
383+
/// You can spawn a task to use the API using [`crate::async_runtime::spawn`] or [`std::thread::spawn`] to prevent the panic.
372384
pub fn is_fullscreen(&self) -> crate::Result<bool> {
373385
self.window.dispatcher.is_fullscreen().map_err(Into::into)
374386
}
@@ -377,8 +389,10 @@ impl<R: Runtime> Window<R> {
377389
///
378390
/// # Panics
379391
///
380-
/// Panics if the app is not running yet, usually when called on the [`setup`](crate::Builder#method.setup) closure.
381-
/// You can spawn a task to use the API using the [`async_runtime`](crate::async_runtime) to prevent the panic.
392+
/// - Panics if the event loop is not running yet, usually when called on the [`setup`](crate::Builder#method.setup) closure.
393+
/// - Panics when called on the main thread, usually on the [`run`](crate::App#method.run) closure.
394+
///
395+
/// You can spawn a task to use the API using [`crate::async_runtime::spawn`] or [`std::thread::spawn`] to prevent the panic.
382396
pub fn is_maximized(&self) -> crate::Result<bool> {
383397
self.window.dispatcher.is_maximized().map_err(Into::into)
384398
}
@@ -387,8 +401,10 @@ impl<R: Runtime> Window<R> {
387401
///
388402
/// # Panics
389403
///
390-
/// Panics if the app is not running yet, usually when called on the [`setup`](crate::Builder#method.setup) closure.
391-
/// You can spawn a task to use the API using the [`async_runtime`](crate::async_runtime) to prevent the panic.
404+
/// - Panics if the event loop is not running yet, usually when called on the [`setup`](crate::Builder#method.setup) closure.
405+
/// - Panics when called on the main thread, usually on the [`run`](crate::App#method.run) closure.
406+
///
407+
/// You can spawn a task to use the API using [`crate::async_runtime::spawn`] or [`std::thread::spawn`] to prevent the panic.
392408
pub fn is_decorated(&self) -> crate::Result<bool> {
393409
self.window.dispatcher.is_decorated().map_err(Into::into)
394410
}
@@ -397,8 +413,10 @@ impl<R: Runtime> Window<R> {
397413
///
398414
/// # Panics
399415
///
400-
/// Panics if the app is not running yet, usually when called on the [`setup`](crate::Builder#method.setup) closure.
401-
/// You can spawn a task to use the API using the [`async_runtime`](crate::async_runtime) to prevent the panic.
416+
/// - Panics if the event loop is not running yet, usually when called on the [`setup`](crate::Builder#method.setup) closure.
417+
/// - Panics when called on the main thread, usually on the [`run`](crate::App#method.run) closure.
418+
///
419+
/// You can spawn a task to use the API using [`crate::async_runtime::spawn`] or [`std::thread::spawn`] to prevent the panic.
402420
pub fn is_resizable(&self) -> crate::Result<bool> {
403421
self.window.dispatcher.is_resizable().map_err(Into::into)
404422
}
@@ -407,8 +425,10 @@ impl<R: Runtime> Window<R> {
407425
///
408426
/// # Panics
409427
///
410-
/// Panics if the app is not running yet, usually when called on the [`setup`](crate::Builder#method.setup) closure.
411-
/// You can spawn a task to use the API using the [`async_runtime`](crate::async_runtime) to prevent the panic.
428+
/// - Panics if the event loop is not running yet, usually when called on the [`setup`](crate::Builder#method.setup) closure.
429+
/// - Panics when called on the main thread, usually on the [`run`](crate::App#method.run) closure.
430+
///
431+
/// You can spawn a task to use the API using [`crate::async_runtime::spawn`] or [`std::thread::spawn`] to prevent the panic.
412432
pub fn is_visible(&self) -> crate::Result<bool> {
413433
self.window.dispatcher.is_visible().map_err(Into::into)
414434
}
@@ -423,8 +443,10 @@ impl<R: Runtime> Window<R> {
423443
///
424444
/// # Panics
425445
///
426-
/// Panics if the app is not running yet, usually when called on the [`setup`](crate::Builder#method.setup) closure.
427-
/// You can spawn a task to use the API using the [`async_runtime`](crate::async_runtime) to prevent the panic.
446+
/// - Panics if the event loop is not running yet, usually when called on the [`setup`](crate::Builder#method.setup) closure.
447+
/// - Panics when called on the main thread, usually on the [`run`](crate::App#method.run) closure.
448+
///
449+
/// You can spawn a task to use the API using [`crate::async_runtime::spawn`] or [`std::thread::spawn`] to prevent the panic.
428450
pub fn current_monitor(&self) -> crate::Result<Option<Monitor>> {
429451
self
430452
.window
@@ -444,8 +466,10 @@ impl<R: Runtime> Window<R> {
444466
///
445467
/// # Panics
446468
///
447-
/// Panics if the app is not running yet, usually when called on the [`setup`](crate::Builder#method.setup) closure.
448-
/// You can spawn a task to use the API using the [`async_runtime`](crate::async_runtime) to prevent the panic.
469+
/// - Panics if the event loop is not running yet, usually when called on the [`setup`](crate::Builder#method.setup) closure.
470+
/// - Panics when called on the main thread, usually on the [`run`](crate::App#method.run) closure.
471+
///
472+
/// You can spawn a task to use the API using [`crate::async_runtime::spawn`] or [`std::thread::spawn`] to prevent the panic.
449473
pub fn primary_monitor(&self) -> crate::Result<Option<Monitor>> {
450474
self
451475
.window
@@ -463,8 +487,10 @@ impl<R: Runtime> Window<R> {
463487
///
464488
/// # Panics
465489
///
466-
/// Panics if the app is not running yet, usually when called on the [`setup`](crate::Builder#method.setup) closure.
467-
/// You can spawn a task to use the API using the [`async_runtime`](crate::async_runtime) to prevent the panic.
490+
/// - Panics if the event loop is not running yet, usually when called on the [`setup`](crate::Builder#method.setup) closure.
491+
/// - Panics when called on the main thread, usually on the [`run`](crate::App#method.run) closure.
492+
///
493+
/// You can spawn a task to use the API using [`crate::async_runtime::spawn`] or [`std::thread::spawn`] to prevent the panic.
468494
pub fn available_monitors(&self) -> crate::Result<Vec<Monitor>> {
469495
self
470496
.window
@@ -478,8 +504,10 @@ impl<R: Runtime> Window<R> {
478504
///
479505
/// # Panics
480506
///
481-
/// Panics if the app is not running yet, usually when called on the [`setup`](crate::Builder#method.setup) closure.
482-
/// You can spawn a task to use the API using the [`async_runtime`](crate::async_runtime) to prevent the panic.
507+
/// - Panics if the event loop is not running yet, usually when called on the [`setup`](crate::Builder#method.setup) closure.
508+
/// - Panics when called on the main thread, usually on the [`run`](crate::App#method.run) closure.
509+
///
510+
/// You can spawn a task to use the API using [`crate::async_runtime::spawn`] or [`std::thread::spawn`] to prevent the panic.
483511
#[cfg(target_os = "macos")]
484512
pub fn ns_window(&self) -> crate::Result<*mut std::ffi::c_void> {
485513
self.window.dispatcher.ns_window().map_err(Into::into)
@@ -488,8 +516,10 @@ impl<R: Runtime> Window<R> {
488516
///
489517
/// # Panics
490518
///
491-
/// Panics if the app is not running yet, usually when called on the [`setup`](crate::Builder#method.setup) closure.
492-
/// You can spawn a task to use the API using the [`async_runtime`](crate::async_runtime) to prevent the panic.
519+
/// - Panics if the event loop is not running yet, usually when called on the [`setup`](crate::Builder#method.setup) closure.
520+
/// - Panics when called on the main thread, usually on the [`run`](crate::App#method.run) closure.
521+
///
522+
/// You can spawn a task to use the API using [`crate::async_runtime::spawn`] or [`std::thread::spawn`] to prevent the panic.
493523
#[cfg(windows)]
494524
pub fn hwnd(&self) -> crate::Result<*mut std::ffi::c_void> {
495525
self

core/tauri/src/window/menu.rs

+8-4
Original file line numberDiff line numberDiff line change
@@ -86,8 +86,10 @@ impl<R: Runtime> MenuHandle<R> {
8686
///
8787
/// # Panics
8888
///
89-
/// Panics if the app is not running yet, usually when called on the [`setup`](crate::Builder#method.setup) closure.
90-
/// You can spawn a task to use the API using the [`async_runtime`](crate::async_runtime) to prevent the panic.
89+
/// - Panics if the event loop is not running yet, usually when called on the [`setup`](crate::Builder#method.setup) closure.
90+
/// - Panics when called on the main thread, usually on the [`run`](crate::App#method.run) closure.
91+
///
92+
/// You can spawn a task to use the API using [`crate::async_runtime::spawn`] or [`std::thread::spawn`] to prevent the panic.
9193
pub fn is_visible(&self) -> crate::Result<bool> {
9294
self.dispatcher.is_menu_visible().map_err(Into::into)
9395
}
@@ -96,8 +98,10 @@ impl<R: Runtime> MenuHandle<R> {
9698
///
9799
/// # Panics
98100
///
99-
/// Panics if the app is not running yet, usually when called on the [`setup`](crate::Builder#method.setup) closure.
100-
/// You can spawn a task to use the API using the [`async_runtime`](crate::async_runtime) to prevent the panic.
101+
/// - Panics if the event loop is not running yet, usually when called on the [`setup`](crate::Builder#method.setup) closure.
102+
/// - Panics when called on the main thread, usually on the [`run`](crate::App#method.run) closure.
103+
///
104+
/// You can spawn a task to use the API using [`crate::async_runtime::spawn`] or [`std::thread::spawn`] to prevent the panic.
101105
pub fn toggle(&self) -> crate::Result<()> {
102106
if self.is_visible()? {
103107
self.hide()

0 commit comments

Comments
 (0)