mirror of https://github.com/tauri-apps/tauri
fix(tray): build tray on main thread (#11583)
This commit is contained in:
parent
f37e97d410
commit
4191a7a53d
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
"tauri": "patch:bug"
|
||||
---
|
||||
|
||||
Fix tray events not fired for tray icons created inside an async command.
|
|
@ -1011,6 +1011,15 @@ pub(crate) mod sealed {
|
|||
}
|
||||
}
|
||||
|
||||
struct UnsafeSend<T>(T);
|
||||
unsafe impl<T> Send for UnsafeSend<T> {}
|
||||
|
||||
impl<T> UnsafeSend<T> {
|
||||
fn take(self) -> T {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
macro_rules! run_main_thread {
|
||||
($handle:ident, $ex:expr) => {{
|
||||
|
|
|
@ -75,7 +75,6 @@ macro_rules! gen_wrappers {
|
|||
app_handle: $crate::AppHandle<R>,
|
||||
}
|
||||
|
||||
|
||||
/// # Safety
|
||||
///
|
||||
/// We make sure it always runs on the main thread.
|
||||
|
@ -96,11 +95,9 @@ macro_rules! gen_wrappers {
|
|||
|
||||
impl<R: Runtime> Drop for $inner<R> {
|
||||
fn drop(&mut self) {
|
||||
struct SafeSend<T>(T);
|
||||
unsafe impl<T> Send for SafeSend<T> {}
|
||||
|
||||
let inner = self.inner.take();
|
||||
let inner = SafeSend(inner);
|
||||
// SAFETY: inner was created on main thread and is being dropped on main thread
|
||||
let inner = $crate::UnsafeSend(inner);
|
||||
let _ = self.app_handle.run_on_main_thread(move || {
|
||||
drop(inner);
|
||||
});
|
||||
|
|
|
@ -10,6 +10,7 @@ use crate::app::{GlobalMenuEventListener, GlobalTrayIconEventListener};
|
|||
use crate::menu::ContextMenu;
|
||||
use crate::menu::MenuEvent;
|
||||
use crate::resources::Resource;
|
||||
use crate::UnsafeSend;
|
||||
use crate::{
|
||||
image::Image, menu::run_item_main_thread, AppHandle, Manager, PhysicalPosition, Rect, Runtime,
|
||||
};
|
||||
|
@ -342,10 +343,24 @@ impl<R: Runtime> TrayIconBuilder<R> {
|
|||
/// Builds and adds a new [`TrayIcon`] to the system tray.
|
||||
pub fn build<M: Manager<R>>(self, manager: &M) -> crate::Result<TrayIcon<R>> {
|
||||
let id = self.id().clone();
|
||||
let inner = self.inner.build()?;
|
||||
|
||||
// SAFETY:
|
||||
// the menu within this builder was created on main thread
|
||||
// and will be accessed on the main thread
|
||||
let unsafe_builder = UnsafeSend(self.inner);
|
||||
|
||||
let (tx, rx) = std::sync::mpsc::channel();
|
||||
let unsafe_tray = manager
|
||||
.app_handle()
|
||||
.run_on_main_thread(move || {
|
||||
// SAFETY: will only be accessed on main thread
|
||||
let _ = tx.send(unsafe_builder.take().build().map(UnsafeSend));
|
||||
})
|
||||
.and_then(|_| rx.recv().map_err(|_| crate::Error::FailedToReceiveMessage))??;
|
||||
|
||||
let icon = TrayIcon {
|
||||
id,
|
||||
inner,
|
||||
inner: unsafe_tray.take(),
|
||||
app_handle: manager.app_handle().clone(),
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue