Skip to content

Commit 4221124

Browse files
fix: use app's resource table for storing tray icons (#13316)
* Use app's resource table for storing tray icons * Clean up * Move remove tray logic to Resource::close
1 parent b985eaf commit 4221124

File tree

5 files changed

+91
-103
lines changed

5 files changed

+91
-103
lines changed

crates/tauri-cli/src/interface/rust.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1036,7 +1036,7 @@ impl RustAppSettings {
10361036
.product_name
10371037
.clone()
10381038
.unwrap_or_else(|| cargo_package_settings.name.clone()),
1039-
version: version.clone(),
1039+
version,
10401040
description: cargo_package_settings
10411041
.description
10421042
.clone()

crates/tauri/src/app.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -741,7 +741,7 @@ macro_rules! shared_app_impl {
741741
I: ?Sized,
742742
TrayIconId: PartialEq<&'a I>,
743743
{
744-
self.manager.tray.tray_by_id(id)
744+
self.manager.tray.tray_by_id(self.app_handle(), id)
745745
}
746746

747747
/// Removes a tray icon using the provided id from tauri's internal state and returns it.
@@ -755,7 +755,7 @@ macro_rules! shared_app_impl {
755755
I: ?Sized,
756756
TrayIconId: PartialEq<&'a I>,
757757
{
758-
self.manager.tray.remove_tray_by_id(id)
758+
self.manager.tray.remove_tray_by_id(self.app_handle(), id)
759759
}
760760

761761
/// Gets the app's configuration, defined on the `tauri.conf.json` file.

crates/tauri/src/manager/tray.rs

Lines changed: 38 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,23 @@
22
// SPDX-License-Identifier: Apache-2.0
33
// SPDX-License-Identifier: MIT
44

5-
use std::{collections::HashMap, fmt, sync::Mutex};
5+
use std::{
6+
collections::HashMap,
7+
fmt,
8+
sync::{Arc, Mutex},
9+
};
610

711
use crate::{
812
app::GlobalTrayIconEventListener,
913
image::Image,
1014
tray::{TrayIcon, TrayIconEvent, TrayIconId},
11-
AppHandle, Runtime,
15+
AppHandle, Manager, Resource, ResourceId, Runtime,
1216
};
1317

1418
pub struct TrayManager<R: Runtime> {
1519
pub(crate) icon: Option<Image<'static>>,
1620
/// Tray icons
17-
pub(crate) icons: Mutex<Vec<TrayIcon<R>>>,
21+
pub(crate) icons: Mutex<Vec<(TrayIconId, ResourceId)>>,
1822
/// Global Tray icon event listeners.
1923
pub(crate) global_event_listeners: Mutex<Vec<GlobalTrayIconEventListener<AppHandle<R>>>>,
2024
/// Tray icon event listeners.
@@ -41,30 +45,46 @@ impl<R: Runtime> TrayManager<R> {
4145
.push(Box::new(handler));
4246
}
4347

44-
pub fn tray_by_id<'a, I>(&self, id: &'a I) -> Option<TrayIcon<R>>
48+
pub fn tray_by_id<'a, I>(&self, app: &AppHandle<R>, id: &'a I) -> Option<TrayIcon<R>>
4549
where
4650
I: ?Sized,
4751
TrayIconId: PartialEq<&'a I>,
4852
{
49-
self
50-
.icons
51-
.lock()
52-
.unwrap()
53-
.iter()
54-
.find(|t| t.id() == &id)
55-
.cloned()
53+
let icons = self.icons.lock().unwrap();
54+
icons.iter().find_map(|(tray_icon_id, rid)| {
55+
if tray_icon_id == &id {
56+
let icon = app.resources_table().get::<TrayIcon<R>>(*rid).ok()?;
57+
Some(Arc::unwrap_or_clone(icon))
58+
} else {
59+
None
60+
}
61+
})
62+
}
63+
64+
pub fn tray_resource_by_id<'a, I>(&self, id: &'a I) -> Option<ResourceId>
65+
where
66+
I: ?Sized,
67+
TrayIconId: PartialEq<&'a I>,
68+
{
69+
let icons = self.icons.lock().unwrap();
70+
icons.iter().find_map(|(tray_icon_id, rid)| {
71+
if tray_icon_id == &id {
72+
Some(*rid)
73+
} else {
74+
None
75+
}
76+
})
5677
}
5778

58-
pub fn remove_tray_by_id<'a, I>(&self, id: &'a I) -> Option<TrayIcon<R>>
79+
pub fn remove_tray_by_id<'a, I>(&self, app: &AppHandle<R>, id: &'a I) -> Option<TrayIcon<R>>
5980
where
6081
I: ?Sized,
6182
TrayIconId: PartialEq<&'a I>,
6283
{
63-
let mut icons = self.icons.lock().unwrap();
64-
let idx = icons.iter().position(|t| t.id() == &id);
65-
if let Some(idx) = idx {
66-
return Some(icons.swap_remove(idx));
67-
}
68-
None
84+
let rid = self.tray_resource_by_id(id)?;
85+
let icon = app.resources_table().take::<TrayIcon<R>>(rid).ok()?;
86+
let icon_to_return = icon.clone();
87+
icon.close();
88+
Some(Arc::unwrap_or_clone(icon_to_return))
6989
}
7090
}

crates/tauri/src/tray/mod.rs

Lines changed: 25 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,10 @@ use crate::app::{GlobalMenuEventListener, GlobalTrayIconEventListener};
1010
use crate::menu::ContextMenu;
1111
use crate::menu::MenuEvent;
1212
use crate::resources::Resource;
13-
use crate::UnsafeSend;
1413
use crate::{
1514
image::Image, menu::run_item_main_thread, AppHandle, Manager, PhysicalPosition, Rect, Runtime,
1615
};
16+
use crate::{ResourceId, UnsafeSend};
1717
use serde::Serialize;
1818
use std::path::Path;
1919
pub use tray_icon::TrayIconId;
@@ -358,8 +358,10 @@ impl<R: Runtime> TrayIconBuilder<R> {
358358
self.inner.id()
359359
}
360360

361-
/// Builds and adds a new [`TrayIcon`] to the system tray.
362-
pub fn build<M: Manager<R>>(self, manager: &M) -> crate::Result<TrayIcon<R>> {
361+
pub(crate) fn build_inner(
362+
self,
363+
app_handle: &AppHandle<R>,
364+
) -> crate::Result<(TrayIcon<R>, ResourceId)> {
363365
let id = self.id().clone();
364366

365367
// SAFETY:
@@ -368,8 +370,7 @@ impl<R: Runtime> TrayIconBuilder<R> {
368370
let unsafe_builder = UnsafeSend(self.inner);
369371

370372
let (tx, rx) = std::sync::mpsc::channel();
371-
let unsafe_tray = manager
372-
.app_handle()
373+
let unsafe_tray = app_handle
373374
.run_on_main_thread(move || {
374375
// SAFETY: will only be accessed on main thread
375376
let _ = tx.send(unsafe_builder.take().build().map(UnsafeSend));
@@ -379,15 +380,21 @@ impl<R: Runtime> TrayIconBuilder<R> {
379380
let icon = TrayIcon {
380381
id,
381382
inner: unsafe_tray.take(),
382-
app_handle: manager.app_handle().clone(),
383+
app_handle: app_handle.clone(),
383384
};
384385

385-
icon.register(
386+
let rid = icon.register(
386387
&icon.app_handle,
387388
self.on_menu_event,
388389
self.on_tray_icon_event,
389390
);
390391

392+
Ok((icon, rid))
393+
}
394+
395+
/// Builds and adds a new [`TrayIcon`] to the system tray.
396+
pub fn build<M: Manager<R>>(self, manager: &M) -> crate::Result<TrayIcon<R>> {
397+
let (icon, _rid) = self.build_inner(manager.app_handle())?;
391398
Ok(icon)
392399
}
393400
}
@@ -426,7 +433,7 @@ impl<R: Runtime> TrayIcon<R> {
426433
app_handle: &AppHandle<R>,
427434
on_menu_event: Option<GlobalMenuEventListener<AppHandle<R>>>,
428435
on_tray_icon_event: Option<GlobalTrayIconEventListener<TrayIcon<R>>>,
429-
) {
436+
) -> ResourceId {
430437
if let Some(handler) = on_menu_event {
431438
app_handle
432439
.manager
@@ -447,13 +454,15 @@ impl<R: Runtime> TrayIcon<R> {
447454
.insert(self.id.clone(), handler);
448455
}
449456

457+
let rid = app_handle.resources_table().add(self.clone());
450458
app_handle
451459
.manager
452460
.tray
453461
.icons
454462
.lock()
455463
.unwrap()
456-
.push(self.clone());
464+
.push((self.id().clone(), rid));
465+
rid
457466
}
458467

459468
/// The application handle associated with this type.
@@ -598,14 +607,13 @@ impl<R: Runtime> TrayIcon<R> {
598607

599608
impl<R: Runtime> Resource for TrayIcon<R> {
600609
fn close(self: std::sync::Arc<Self>) {
601-
self
602-
.app_handle
603-
.state::<plugin::TrayIcons>()
604-
.icons
605-
.lock()
606-
.unwrap()
607-
.remove(&self.id.0);
608-
self.app_handle.remove_tray_by_id(&self.id);
610+
let mut icons = self.app_handle.manager.tray.icons.lock().unwrap();
611+
for (i, (tray_icon_id, _rid)) in icons.iter_mut().enumerate() {
612+
if tray_icon_id == &self.id {
613+
icons.swap_remove(i);
614+
return;
615+
}
616+
}
609617
}
610618
}
611619

0 commit comments

Comments
 (0)