1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
// Copyright 2019-2021 Tauri Programme within The Commons Conservancy
// SPDX-License-Identifier: Apache-2.0

//! **UNSTABLE** -- The `SystemTray` struct and associated types.
//!
//! Use [SystemTrayBuilder][tray_builder] to create your tray instance.
//!
//! [ContextMenu][context_menu] is used to created a Window menu on Windows and Linux. On macOS it's used in the menubar.
//!
//! ```rust,ignore
//! let mut tray_menu = ContextMenu::new();
//! let icon = include_bytes!("my_icon.png").to_vec();
//!
//! tray_menu.add_item(MenuItemAttributes::new("My menu item"));
//!
//! let mut system_tray = SystemTrayBuilder::new(icon, Some(tray_menu))
//!   .build(&event_loop)
//!   .unwrap();
//! ```
//!
//! # Windows
//! The icon is not removed automatically.
//!
//! Use `SystemTrayExtWindows` and use the `remove()` function when your application is closing.
//!
//! # Linux
//! A menu is required or the tray return an error containing `assertion 'G_IS_DBUS_CONNECTION (connection)'`.
//!
//! [tray_builder]: crate::system_tray::SystemTrayBuilder
//! [menu_bar]: crate::menu::MenuBar
//! [context_menu]: crate::menu::ContextMenu

use crate::{
  error::OsError,
  event_loop::EventLoopWindowTarget,
  menu::ContextMenu,
  platform_impl::{
    SystemTray as SystemTrayPlatform, SystemTrayBuilder as SystemTrayBuilderPlatform,
  },
};
/// Object that allows you to build SystemTray instance.
pub struct SystemTrayBuilder(SystemTrayBuilderPlatform);

#[cfg(target_os = "linux")]
use std::path::PathBuf;

impl SystemTrayBuilder {
  /// Creates a new SystemTray for platforms where this is appropriate.
  ///
  /// ## Platform-specific
  ///
  /// - **macOS / Windows:**: receive icon as bytes (`Vec<u8>`)
  /// - **Linux:**: receive icon's path (`PathBuf`)
  #[cfg(not(target_os = "linux"))]
  pub fn new(icon: Vec<u8>, tray_menu: Option<ContextMenu>) -> Self {
    Self(SystemTrayBuilderPlatform::new(
      icon,
      tray_menu.map(|m| m.0.menu_platform),
    ))
  }

  /// Creates a new SystemTray for platforms where this is appropriate.
  ///
  /// ## Platform-specific
  ///
  /// - **macOS / Windows:**: receive icon as bytes (`Vec<u8>`)
  /// - **Linux:**: receive icon's path (`PathBuf`)
  #[cfg(target_os = "linux")]
  pub fn new(icon: PathBuf, tray_menu: Option<ContextMenu>) -> Self {
    Self(SystemTrayBuilderPlatform::new(
      icon,
      tray_menu.map(|m| m.0.menu_platform),
    ))
  }

  /// Builds the SystemTray.
  ///
  /// Possible causes of error include denied permission, incompatible system, and lack of memory.
  ///
  /// ## Platform-specific
  ///
  /// - **Windows:**: The icon is not removed automatically. Use `SystemTrayExtWindows` and use the `remove()` function when your application is closing.
  pub fn build<T: 'static>(
    self,
    _window_target: &EventLoopWindowTarget<T>,
  ) -> Result<SystemTray, OsError> {
    self.0.build(_window_target)
  }
}

/// Represents a System Tray instance.
pub struct SystemTray(pub SystemTrayPlatform);

impl SystemTray {
  /// Set new tray icon.
  ///
  /// ## Platform-specific
  ///
  /// - **macOS / Windows:**: receive icon as bytes (`Vec<u8>`)
  /// - **Linux:**: receive icon's path (`PathBuf`)
  #[cfg(not(target_os = "linux"))]
  pub fn set_icon(&mut self, icon: Vec<u8>) {
    self.0.set_icon(icon)
  }

  /// Set new tray icon.
  ///
  /// ## Platform-specific
  ///
  /// - **macOS / Windows:**: receive icon as bytes (`Vec<u8>`)
  /// - **Linux:**: receive icon's path (`PathBuf`)
  #[cfg(target_os = "linux")]
  pub fn set_icon(&mut self, icon: PathBuf) {
    self.0.set_icon(icon)
  }

  /// Set new tray menu.
  pub fn set_menu(&mut self, tray_menu: &ContextMenu) {
    self.0.set_menu(&tray_menu.0.menu_platform)
  }
}