plugin.rs 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311
  1. // Copyright 2019-2024 Tauri Programme within The Commons Conservancy
  2. // SPDX-License-Identifier: Apache-2.0
  3. // SPDX-License-Identifier: MIT
  4. //! The tauri plugin to create and manipulate windows from JS.
  5. use crate::{
  6. plugin::{Builder, TauriPlugin},
  7. Runtime,
  8. };
  9. #[cfg(desktop)]
  10. mod desktop_commands {
  11. use tauri_runtime::{window::WindowSizeConstraints, ResizeDirection};
  12. use tauri_utils::TitleBarStyle;
  13. use super::*;
  14. use crate::{
  15. command,
  16. sealed::ManagerBase,
  17. utils::config::{WindowConfig, WindowEffectsConfig},
  18. window::Color,
  19. window::{ProgressBarState, WindowBuilder},
  20. AppHandle, CursorIcon, Manager, Monitor, PhysicalPosition, PhysicalSize, Position, Size, Theme,
  21. UserAttentionType, Webview, Window,
  22. };
  23. #[command(root = "crate")]
  24. pub async fn get_all_windows<R: Runtime>(app: AppHandle<R>) -> Vec<String> {
  25. app.manager().windows().keys().cloned().collect()
  26. }
  27. #[command(root = "crate")]
  28. pub async fn create<R: Runtime>(app: AppHandle<R>, options: WindowConfig) -> crate::Result<()> {
  29. WindowBuilder::from_config(&app, &options)?.build()?;
  30. Ok(())
  31. }
  32. fn get_window<R: Runtime>(window: Window<R>, label: Option<String>) -> crate::Result<Window<R>> {
  33. match label {
  34. Some(l) if !l.is_empty() => window
  35. .manager()
  36. .get_window(&l)
  37. .ok_or(crate::Error::WindowNotFound),
  38. _ => Ok(window),
  39. }
  40. }
  41. macro_rules! getter {
  42. ($cmd: ident, $ret: ty) => {
  43. #[command(root = "crate")]
  44. pub async fn $cmd<R: Runtime>(
  45. window: Window<R>,
  46. label: Option<String>,
  47. ) -> crate::Result<$ret> {
  48. get_window(window, label)?.$cmd().map_err(Into::into)
  49. }
  50. };
  51. }
  52. macro_rules! setter {
  53. ($cmd: ident) => {
  54. #[command(root = "crate")]
  55. pub async fn $cmd<R: Runtime>(window: Window<R>, label: Option<String>) -> crate::Result<()> {
  56. get_window(window, label)?.$cmd().map_err(Into::into)
  57. }
  58. };
  59. ($cmd: ident, $input: ty) => {
  60. #[command(root = "crate")]
  61. pub async fn $cmd<R: Runtime>(
  62. window: Window<R>,
  63. label: Option<String>,
  64. value: $input,
  65. ) -> crate::Result<()> {
  66. get_window(window, label)?.$cmd(value).map_err(Into::into)
  67. }
  68. };
  69. }
  70. getter!(scale_factor, f64);
  71. getter!(inner_position, PhysicalPosition<i32>);
  72. getter!(outer_position, PhysicalPosition<i32>);
  73. getter!(inner_size, PhysicalSize<u32>);
  74. getter!(outer_size, PhysicalSize<u32>);
  75. getter!(is_fullscreen, bool);
  76. getter!(is_minimized, bool);
  77. getter!(is_maximized, bool);
  78. getter!(is_focused, bool);
  79. getter!(is_decorated, bool);
  80. getter!(is_resizable, bool);
  81. getter!(is_maximizable, bool);
  82. getter!(is_minimizable, bool);
  83. getter!(is_closable, bool);
  84. getter!(is_visible, bool);
  85. getter!(is_enabled, bool);
  86. getter!(title, String);
  87. getter!(current_monitor, Option<Monitor>);
  88. getter!(primary_monitor, Option<Monitor>);
  89. getter!(available_monitors, Vec<Monitor>);
  90. getter!(cursor_position, PhysicalPosition<f64>);
  91. getter!(theme, Theme);
  92. setter!(center);
  93. setter!(request_user_attention, Option<UserAttentionType>);
  94. setter!(set_resizable, bool);
  95. setter!(set_maximizable, bool);
  96. setter!(set_minimizable, bool);
  97. setter!(set_closable, bool);
  98. setter!(set_title, &str);
  99. setter!(maximize);
  100. setter!(unmaximize);
  101. setter!(minimize);
  102. setter!(unminimize);
  103. setter!(show);
  104. setter!(hide);
  105. setter!(close);
  106. setter!(destroy);
  107. setter!(set_decorations, bool);
  108. setter!(set_shadow, bool);
  109. setter!(set_effects, Option<WindowEffectsConfig>);
  110. setter!(set_always_on_top, bool);
  111. setter!(set_always_on_bottom, bool);
  112. setter!(set_content_protected, bool);
  113. setter!(set_size, Size);
  114. setter!(set_min_size, Option<Size>);
  115. setter!(set_max_size, Option<Size>);
  116. setter!(set_position, Position);
  117. setter!(set_fullscreen, bool);
  118. setter!(set_focus);
  119. setter!(set_skip_taskbar, bool);
  120. setter!(set_cursor_grab, bool);
  121. setter!(set_cursor_visible, bool);
  122. setter!(set_background_color, Option<Color>);
  123. setter!(set_cursor_icon, CursorIcon);
  124. setter!(set_cursor_position, Position);
  125. setter!(set_ignore_cursor_events, bool);
  126. setter!(start_dragging);
  127. setter!(start_resize_dragging, ResizeDirection);
  128. setter!(set_progress_bar, ProgressBarState);
  129. setter!(set_visible_on_all_workspaces, bool);
  130. setter!(set_title_bar_style, TitleBarStyle);
  131. setter!(set_size_constraints, WindowSizeConstraints);
  132. setter!(set_theme, Option<Theme>);
  133. setter!(set_enabled, bool);
  134. #[command(root = "crate")]
  135. pub async fn set_icon<R: Runtime>(
  136. webview: Webview<R>,
  137. window: Window<R>,
  138. label: Option<String>,
  139. value: crate::image::JsImage,
  140. ) -> crate::Result<()> {
  141. let window = get_window(window, label)?;
  142. let resources_table = webview.resources_table();
  143. window
  144. .set_icon(value.into_img(&resources_table)?.as_ref().clone())
  145. .map_err(Into::into)
  146. }
  147. #[command(root = "crate")]
  148. pub async fn toggle_maximize<R: Runtime>(
  149. window: Window<R>,
  150. label: Option<String>,
  151. ) -> crate::Result<()> {
  152. let window = get_window(window, label)?;
  153. match window.is_maximized()? {
  154. true => window.unmaximize()?,
  155. false => window.maximize()?,
  156. };
  157. Ok(())
  158. }
  159. #[command(root = "crate")]
  160. pub async fn internal_toggle_maximize<R: Runtime>(
  161. window: Window<R>,
  162. label: Option<String>,
  163. ) -> crate::Result<()> {
  164. let window = get_window(window, label)?;
  165. if window.is_resizable()? {
  166. match window.is_maximized()? {
  167. true => window.unmaximize()?,
  168. false => window.maximize()?,
  169. };
  170. }
  171. Ok(())
  172. }
  173. #[command(root = "crate")]
  174. pub async fn monitor_from_point<R: Runtime>(
  175. window: Window<R>,
  176. label: Option<String>,
  177. x: f64,
  178. y: f64,
  179. ) -> crate::Result<Option<Monitor>> {
  180. let window = get_window(window, label)?;
  181. window.monitor_from_point(x, y)
  182. }
  183. }
  184. /// Initializes the plugin.
  185. pub fn init<R: Runtime>() -> TauriPlugin<R> {
  186. use serialize_to_javascript::{default_template, DefaultTemplate, Template};
  187. let mut init_script = String::new();
  188. #[derive(Template)]
  189. #[default_template("./scripts/drag.js")]
  190. struct Drag<'a> {
  191. os_name: &'a str,
  192. }
  193. init_script.push_str(
  194. &Drag {
  195. os_name: std::env::consts::OS,
  196. }
  197. .render_default(&Default::default())
  198. .unwrap()
  199. .into_string(),
  200. );
  201. Builder::new("window")
  202. .js_init_script(init_script)
  203. .invoke_handler(|invoke| {
  204. #[cfg(desktop)]
  205. {
  206. let handler: Box<dyn Fn(crate::ipc::Invoke<R>) -> bool> =
  207. Box::new(crate::generate_handler![
  208. desktop_commands::create,
  209. // getters
  210. desktop_commands::get_all_windows,
  211. desktop_commands::scale_factor,
  212. desktop_commands::inner_position,
  213. desktop_commands::outer_position,
  214. desktop_commands::inner_size,
  215. desktop_commands::outer_size,
  216. desktop_commands::is_fullscreen,
  217. desktop_commands::is_minimized,
  218. desktop_commands::is_maximized,
  219. desktop_commands::is_focused,
  220. desktop_commands::is_decorated,
  221. desktop_commands::is_resizable,
  222. desktop_commands::is_maximizable,
  223. desktop_commands::is_minimizable,
  224. desktop_commands::is_closable,
  225. desktop_commands::is_visible,
  226. desktop_commands::is_enabled,
  227. desktop_commands::title,
  228. desktop_commands::current_monitor,
  229. desktop_commands::primary_monitor,
  230. desktop_commands::monitor_from_point,
  231. desktop_commands::available_monitors,
  232. desktop_commands::cursor_position,
  233. desktop_commands::theme,
  234. // setters
  235. desktop_commands::center,
  236. desktop_commands::request_user_attention,
  237. desktop_commands::set_resizable,
  238. desktop_commands::set_maximizable,
  239. desktop_commands::set_minimizable,
  240. desktop_commands::set_closable,
  241. desktop_commands::set_title,
  242. desktop_commands::maximize,
  243. desktop_commands::unmaximize,
  244. desktop_commands::minimize,
  245. desktop_commands::unminimize,
  246. desktop_commands::show,
  247. desktop_commands::hide,
  248. desktop_commands::close,
  249. desktop_commands::destroy,
  250. desktop_commands::set_decorations,
  251. desktop_commands::set_shadow,
  252. desktop_commands::set_effects,
  253. desktop_commands::set_always_on_top,
  254. desktop_commands::set_always_on_bottom,
  255. desktop_commands::set_content_protected,
  256. desktop_commands::set_size,
  257. desktop_commands::set_min_size,
  258. desktop_commands::set_max_size,
  259. desktop_commands::set_size_constraints,
  260. desktop_commands::set_position,
  261. desktop_commands::set_fullscreen,
  262. desktop_commands::set_focus,
  263. desktop_commands::set_enabled,
  264. desktop_commands::set_skip_taskbar,
  265. desktop_commands::set_cursor_grab,
  266. desktop_commands::set_cursor_visible,
  267. desktop_commands::set_cursor_icon,
  268. desktop_commands::set_cursor_position,
  269. desktop_commands::set_ignore_cursor_events,
  270. desktop_commands::start_dragging,
  271. desktop_commands::start_resize_dragging,
  272. desktop_commands::set_progress_bar,
  273. desktop_commands::set_icon,
  274. desktop_commands::set_visible_on_all_workspaces,
  275. desktop_commands::set_background_color,
  276. desktop_commands::set_title_bar_style,
  277. desktop_commands::set_theme,
  278. desktop_commands::toggle_maximize,
  279. desktop_commands::internal_toggle_maximize,
  280. ]);
  281. handler(invoke)
  282. }
  283. #[cfg(mobile)]
  284. {
  285. invoke.resolver.reject("Window API not available on mobile");
  286. true
  287. }
  288. })
  289. .build()
  290. }