system_tray.rs 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. // Copyright 2019-2021 Tauri Programme within The Commons Conservancy
  2. // SPDX-License-Identifier: Apache-2.0
  3. // SPDX-License-Identifier: MIT
  4. pub use tauri_runtime::{
  5. menu::{
  6. Menu, MenuEntry, MenuItem, MenuUpdate, Submenu, SystemTrayMenu, SystemTrayMenuEntry,
  7. SystemTrayMenuItem, TrayHandle,
  8. },
  9. Icon, SystemTrayEvent,
  10. };
  11. pub use wry::application::{
  12. event::TrayEvent,
  13. event_loop::EventLoopProxy,
  14. menu::{
  15. ContextMenu as WryContextMenu, CustomMenuItem as WryCustomMenuItem, MenuItem as WryMenuItem,
  16. },
  17. };
  18. use crate::{Error, Message, Result, TrayMessage};
  19. use tauri_runtime::menu::MenuHash;
  20. use uuid::Uuid;
  21. use std::{
  22. collections::HashMap,
  23. sync::{Arc, Mutex},
  24. };
  25. pub type SystemTrayEventHandler = Box<dyn Fn(&SystemTrayEvent) + Send>;
  26. pub type SystemTrayEventListeners = Arc<Mutex<HashMap<Uuid, SystemTrayEventHandler>>>;
  27. pub type SystemTrayItems = Arc<Mutex<HashMap<u16, WryCustomMenuItem>>>;
  28. #[derive(Debug, Clone)]
  29. pub struct SystemTrayHandle {
  30. pub(crate) proxy: EventLoopProxy<super::Message>,
  31. }
  32. impl TrayHandle for SystemTrayHandle {
  33. fn set_icon(&self, icon: Icon) -> Result<()> {
  34. self
  35. .proxy
  36. .send_event(Message::Tray(TrayMessage::UpdateIcon(icon)))
  37. .map_err(|_| Error::FailedToSendMessage)
  38. }
  39. fn update_item(&self, id: u16, update: MenuUpdate) -> Result<()> {
  40. self
  41. .proxy
  42. .send_event(Message::Tray(TrayMessage::UpdateItem(id, update)))
  43. .map_err(|_| Error::FailedToSendMessage)
  44. }
  45. #[cfg(target_os = "macos")]
  46. fn set_icon_as_template(&self, is_template: bool) -> tauri_runtime::Result<()> {
  47. self
  48. .proxy
  49. .send_event(Message::Tray(TrayMessage::UpdateIconAsTemplate(
  50. is_template,
  51. )))
  52. .map_err(|_| Error::FailedToSendMessage)
  53. }
  54. }
  55. impl From<SystemTrayMenuItem> for crate::MenuItemWrapper {
  56. fn from(item: SystemTrayMenuItem) -> Self {
  57. match item {
  58. SystemTrayMenuItem::Separator => Self(WryMenuItem::Separator),
  59. _ => unimplemented!(),
  60. }
  61. }
  62. }
  63. pub fn to_wry_context_menu(
  64. custom_menu_items: &mut HashMap<MenuHash, WryCustomMenuItem>,
  65. menu: SystemTrayMenu,
  66. ) -> WryContextMenu {
  67. let mut tray_menu = WryContextMenu::new();
  68. for item in menu.items {
  69. match item {
  70. SystemTrayMenuEntry::CustomItem(c) => {
  71. #[allow(unused_mut)]
  72. let mut item = tray_menu.add_item(crate::MenuItemAttributesWrapper::from(&c).0);
  73. #[cfg(target_os = "macos")]
  74. if let Some(native_image) = c.native_image {
  75. item.set_native_image(crate::NativeImageWrapper::from(native_image).0);
  76. }
  77. custom_menu_items.insert(c.id, item);
  78. }
  79. SystemTrayMenuEntry::NativeItem(i) => {
  80. tray_menu.add_native_item(crate::MenuItemWrapper::from(i).0);
  81. }
  82. SystemTrayMenuEntry::Submenu(submenu) => {
  83. tray_menu.add_submenu(
  84. &submenu.title,
  85. submenu.enabled,
  86. to_wry_context_menu(custom_menu_items, submenu.inner),
  87. );
  88. }
  89. }
  90. }
  91. tray_menu
  92. }