lib.rs 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291
  1. // Copyright 2019-2021 Tauri Programme within The Commons Conservancy
  2. // SPDX-License-Identifier: Apache-2.0
  3. // SPDX-License-Identifier: MIT
  4. //! Tauri is a framework for building tiny, blazing fast binaries for all major desktop platforms.
  5. //! Developers can integrate any front-end framework that compiles to HTML, JS and CSS for building their user interface.
  6. //! The backend of the application is a rust-sourced binary with an API that the front-end can interact with.
  7. //!
  8. //! The user interface in Tauri apps currently leverages Cocoa/WebKit on macOS, gtk-webkit2 on Linux and MSHTML (IE10/11) or Webkit via Edge on Windows.
  9. //! Tauri uses (and contributes to) the MIT licensed project that you can find at [webview](https://github.com/webview/webview).
  10. #![warn(missing_docs, rust_2018_idioms)]
  11. /// The Tauri error enum.
  12. pub use error::Error;
  13. pub use tauri_macros::{command, generate_handler};
  14. /// Core API.
  15. pub mod api;
  16. pub(crate) mod app;
  17. /// Async runtime.
  18. pub mod async_runtime;
  19. pub mod command;
  20. /// The Tauri API endpoints.
  21. mod endpoints;
  22. mod error;
  23. mod event;
  24. mod hooks;
  25. mod manager;
  26. pub mod plugin;
  27. /// Tauri window.
  28. pub mod window;
  29. use tauri_runtime as runtime;
  30. /// The Tauri-specific settings for your runtime e.g. notification permission status.
  31. pub mod settings;
  32. mod state;
  33. #[cfg(feature = "updater")]
  34. pub mod updater;
  35. #[cfg(feature = "wry")]
  36. pub use tauri_runtime_wry::Wry;
  37. /// `Result<T, ::tauri::Error>`
  38. pub type Result<T> = std::result::Result<T, Error>;
  39. /// A task to run on the main thread.
  40. pub type SyncTask = Box<dyn FnOnce() + Send>;
  41. use crate::{
  42. event::{Event, EventHandler},
  43. runtime::window::PendingWindow,
  44. };
  45. use serde::Serialize;
  46. use std::{borrow::Borrow, collections::HashMap, path::PathBuf, sync::Arc};
  47. // Export types likely to be used by the application.
  48. pub use {
  49. self::api::assets::Assets,
  50. self::api::config::{Config, WindowUrl},
  51. self::app::{App, Builder, GlobalWindowEvent, SystemTrayEvent, WindowMenuEvent},
  52. self::hooks::{
  53. Invoke, InvokeError, InvokeHandler, InvokeMessage, InvokeResolver, InvokeResponse, OnPageLoad,
  54. PageLoadPayload, SetupHook,
  55. },
  56. self::runtime::{
  57. menu::{CustomMenuItem, Menu, MenuId, MenuItem, SystemTrayMenuItem},
  58. tag::{Tag, TagRef},
  59. webview::{WebviewAttributes, WindowBuilder},
  60. window::{
  61. dpi::{LogicalPosition, LogicalSize, PhysicalPosition, PhysicalSize, Pixel, Position, Size},
  62. WindowEvent,
  63. },
  64. Params,
  65. },
  66. self::state::{State, StateManager},
  67. self::window::{MenuEvent, Monitor, Window},
  68. tauri_utils::platform,
  69. };
  70. /// Reads the config file at compile time and generates a [`Context`] based on its content.
  71. ///
  72. /// The default config file path is a `tauri.conf.json` file inside the Cargo manifest directory of
  73. /// the crate being built.
  74. ///
  75. /// # Custom Config Path
  76. ///
  77. /// You may pass a string literal to this macro to specify a custom path for the Tauri config file.
  78. /// If the path is relative, it will be search for relative to the Cargo manifest of the compiling
  79. /// crate.
  80. ///
  81. /// # Note
  82. ///
  83. /// This macro should not be called if you are using [`tauri-build`] to generate the context from
  84. /// inside your build script as it will just cause excess computations that will be discarded. Use
  85. /// either the [`tauri-build] method or this macro - not both.
  86. ///
  87. /// [`tauri-build`]: https://docs.rs/tauri-build
  88. pub use tauri_macros::generate_context;
  89. /// Include a [`Context`] that was generated by [`tauri-build`] inside your build script.
  90. ///
  91. /// You should either use [`tauri-build`] and this macro to include the compile time generated code,
  92. /// or [`generate_context!`]. Do not use both at the same time, as they generate the same code and
  93. /// will cause excess computations that will be discarded.
  94. ///
  95. /// [`tauri-build`]: https://docs.rs/tauri-build
  96. #[macro_export]
  97. macro_rules! tauri_build_context {
  98. () => {
  99. include!(concat!(env!("OUT_DIR"), "/tauri-build-context.rs"))
  100. };
  101. }
  102. /// User supplied data required inside of a Tauri application.
  103. pub struct Context<A: Assets> {
  104. /// The config the application was prepared with.
  105. pub config: Config,
  106. /// The assets to be served directly by Tauri.
  107. pub assets: Arc<A>,
  108. /// The default window icon Tauri should use when creating windows.
  109. pub default_window_icon: Option<Vec<u8>>,
  110. /// The icon to use use on the system tray UI.
  111. #[cfg(target_os = "linux")]
  112. pub system_tray_icon: Option<PathBuf>,
  113. /// The icon to use use on the system tray UI.
  114. #[cfg(not(target_os = "linux"))]
  115. pub system_tray_icon: Option<Vec<u8>>,
  116. /// Package information.
  117. pub package_info: crate::api::PackageInfo,
  118. }
  119. /// Manages a running application.
  120. ///
  121. /// TODO: expand these docs
  122. pub trait Manager<P: Params>: sealed::ManagerBase<P> {
  123. /// The [`Config`] the manager was created with.
  124. fn config(&self) -> Arc<Config> {
  125. self.manager().config()
  126. }
  127. /// Emits a event to all windows.
  128. fn emit_all<E: ?Sized, S>(&self, event: &E, payload: S) -> Result<()>
  129. where
  130. P::Event: Borrow<E>,
  131. E: TagRef<P::Event>,
  132. S: Serialize + Clone,
  133. {
  134. self.manager().emit_filter(event, payload, |_| true)
  135. }
  136. /// Emits an event to a window with the specified label.
  137. fn emit_to<E: ?Sized, L: ?Sized, S: Serialize + Clone>(
  138. &self,
  139. label: &L,
  140. event: &E,
  141. payload: S,
  142. ) -> Result<()>
  143. where
  144. P::Label: Borrow<L>,
  145. P::Event: Borrow<E>,
  146. L: TagRef<P::Label>,
  147. E: TagRef<P::Event>,
  148. {
  149. self
  150. .manager()
  151. .emit_filter(event, payload, |w| label == w.label())
  152. }
  153. /// Listen to a global event.
  154. fn listen_global<E: Into<P::Event>, F>(&self, event: E, handler: F) -> EventHandler
  155. where
  156. F: Fn(Event) + Send + 'static,
  157. {
  158. self.manager().listen(event.into(), None, handler)
  159. }
  160. /// Listen to a global event only once.
  161. fn once_global<E: Into<P::Event>, F>(&self, event: E, handler: F) -> EventHandler
  162. where
  163. F: Fn(Event) + Send + 'static,
  164. {
  165. self.manager().once(event.into(), None, handler)
  166. }
  167. /// Trigger a global event.
  168. fn trigger_global<E: ?Sized>(&self, event: &E, data: Option<String>)
  169. where
  170. P::Event: Borrow<E>,
  171. E: TagRef<P::Event>,
  172. {
  173. self.manager().trigger(event, None, data)
  174. }
  175. /// Remove an event listener.
  176. fn unlisten(&self, handler_id: EventHandler) {
  177. self.manager().unlisten(handler_id)
  178. }
  179. /// Fetch a single window from the manager.
  180. fn get_window<L: ?Sized>(&self, label: &L) -> Option<Window<P>>
  181. where
  182. P::Label: Borrow<L>,
  183. L: TagRef<P::Label>,
  184. {
  185. self.manager().get_window(label)
  186. }
  187. /// Fetch all managed windows.
  188. fn windows(&self) -> HashMap<P::Label, Window<P>> {
  189. self.manager().windows()
  190. }
  191. /// Add `state` to the state managed by the application.
  192. /// See [`tauri::Builder#manage`] for instructions.
  193. fn manage<T>(&self, state: T)
  194. where
  195. T: Send + Sync + 'static,
  196. {
  197. self.manager().state().set(state);
  198. }
  199. /// Gets the managed state for the type `T`.
  200. fn state<T>(&self) -> State<'_, T>
  201. where
  202. T: Send + Sync + 'static,
  203. {
  204. self.manager().inner.state.get()
  205. }
  206. }
  207. /// Prevent implementation details from leaking out of the [`Manager`] trait.
  208. pub(crate) mod sealed {
  209. use crate::manager::WindowManager;
  210. use tauri_runtime::{Params, Runtime};
  211. /// A running [`Runtime`] or a dispatcher to it.
  212. pub enum RuntimeOrDispatch<'r, P: Params> {
  213. /// Reference to the running [`Runtime`].
  214. Runtime(&'r P::Runtime),
  215. /// A dispatcher to the running [`Runtime`].
  216. Dispatch(<P::Runtime as Runtime>::Dispatcher),
  217. }
  218. /// Managed handle to the application runtime.
  219. pub trait ManagerBase<P: Params> {
  220. /// The manager behind the [`Managed`] item.
  221. fn manager(&self) -> &WindowManager<P>;
  222. /// Creates a new [`Window`] on the [`Runtime`] and attaches it to the [`Manager`].
  223. fn create_new_window(
  224. &self,
  225. runtime: RuntimeOrDispatch<'_, P>,
  226. pending: crate::PendingWindow<P>,
  227. ) -> crate::Result<crate::Window<P>> {
  228. use crate::runtime::Dispatch;
  229. let labels = self.manager().labels().into_iter().collect::<Vec<_>>();
  230. let pending = self.manager().prepare_window(pending, &labels)?;
  231. match runtime {
  232. RuntimeOrDispatch::Runtime(runtime) => runtime.create_window(pending).map_err(Into::into),
  233. RuntimeOrDispatch::Dispatch(mut dispatcher) => {
  234. dispatcher.create_window(pending).map_err(Into::into)
  235. }
  236. }
  237. .map(|window| self.manager().attach_window(window))
  238. }
  239. }
  240. }
  241. #[cfg(test)]
  242. mod test {
  243. use proptest::prelude::*;
  244. proptest! {
  245. #![proptest_config(ProptestConfig::with_cases(10000))]
  246. #[test]
  247. // check to see if spawn executes a function.
  248. fn check_spawn_task(task in "[a-z]+") {
  249. // create dummy task function
  250. let dummy_task = async move {
  251. format!("{}-run-dummy-task", task);
  252. };
  253. // call spawn
  254. crate::async_runtime::spawn(dummy_task);
  255. }
  256. }
  257. }