window.rs 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. // Copyright 2019-2021 Tauri Programme within The Commons Conservancy
  2. // SPDX-License-Identifier: Apache-2.0
  3. // SPDX-License-Identifier: MIT
  4. //! A layer between raw [`Runtime`] webview windows and Tauri.
  5. use crate::{
  6. http::{Request as HttpRequest, Response as HttpResponse},
  7. menu::{Menu, MenuEntry, MenuHash, MenuId},
  8. webview::{FileDropHandler, WebviewAttributes, WebviewRpcHandler},
  9. Dispatch, Runtime, WindowBuilder,
  10. };
  11. use serde::Serialize;
  12. use tauri_utils::config::WindowConfig;
  13. use std::{
  14. collections::HashMap,
  15. hash::{Hash, Hasher},
  16. };
  17. type UriSchemeProtocol =
  18. dyn Fn(&HttpRequest) -> Result<HttpResponse, Box<dyn std::error::Error>> + Send + Sync + 'static;
  19. /// UI scaling utilities.
  20. pub mod dpi;
  21. /// An event from a window.
  22. #[derive(Debug, Clone)]
  23. #[non_exhaustive]
  24. pub enum WindowEvent {
  25. /// The size of the window has changed. Contains the client area's new dimensions.
  26. Resized(dpi::PhysicalSize<u32>),
  27. /// The position of the window has changed. Contains the window's new position.
  28. Moved(dpi::PhysicalPosition<i32>),
  29. /// The window has been requested to close.
  30. CloseRequested,
  31. /// The window has been destroyed.
  32. Destroyed,
  33. /// The window gained or lost focus.
  34. ///
  35. /// The parameter is true if the window has gained focus, and false if it has lost focus.
  36. Focused(bool),
  37. /// The window's scale factor has changed.
  38. ///
  39. /// The following user actions can cause DPI changes:
  40. ///
  41. /// - Changing the display's resolution.
  42. /// - Changing the display's scale factor (e.g. in Control Panel on Windows).
  43. /// - Moving the window to a display with a different scale factor.
  44. ScaleFactorChanged {
  45. /// The new scale factor.
  46. scale_factor: f64,
  47. /// The window inner size.
  48. new_inner_size: dpi::PhysicalSize<u32>,
  49. },
  50. }
  51. /// A menu event.
  52. #[derive(Debug, Serialize)]
  53. #[serde(rename_all = "camelCase")]
  54. pub struct MenuEvent {
  55. pub menu_item_id: u16,
  56. }
  57. fn get_menu_ids(map: &mut HashMap<MenuHash, MenuId>, menu: &Menu) {
  58. for item in &menu.items {
  59. match item {
  60. MenuEntry::CustomItem(c) => {
  61. map.insert(c.id, c.id_str.clone());
  62. }
  63. MenuEntry::Submenu(s) => get_menu_ids(map, &s.inner),
  64. _ => {}
  65. }
  66. }
  67. }
  68. /// A webview window that has yet to be built.
  69. pub struct PendingWindow<R: Runtime> {
  70. /// The label that the window will be named.
  71. pub label: String,
  72. /// The [`WindowBuilder`] that the window will be created with.
  73. pub window_builder: <R::Dispatcher as Dispatch>::WindowBuilder,
  74. /// The [`WebviewAttributes`] that the webview will be created with.
  75. pub webview_attributes: WebviewAttributes,
  76. pub uri_scheme_protocols: HashMap<String, Box<UriSchemeProtocol>>,
  77. /// How to handle RPC calls on the webview window.
  78. pub rpc_handler: Option<WebviewRpcHandler<R>>,
  79. /// How to handle a file dropping onto the webview window.
  80. pub file_drop_handler: Option<FileDropHandler<R>>,
  81. /// The resolved URL to load on the webview.
  82. pub url: String,
  83. /// Maps runtime id to a string menu id.
  84. pub menu_ids: HashMap<MenuHash, MenuId>,
  85. }
  86. impl<R: Runtime> PendingWindow<R> {
  87. /// Create a new [`PendingWindow`] with a label and starting url.
  88. pub fn new(
  89. window_builder: <R::Dispatcher as Dispatch>::WindowBuilder,
  90. webview_attributes: WebviewAttributes,
  91. label: impl Into<String>,
  92. ) -> Self {
  93. let mut menu_ids = HashMap::new();
  94. if let Some(menu) = window_builder.get_menu() {
  95. get_menu_ids(&mut menu_ids, menu);
  96. }
  97. Self {
  98. window_builder,
  99. webview_attributes,
  100. uri_scheme_protocols: Default::default(),
  101. label: label.into(),
  102. rpc_handler: None,
  103. file_drop_handler: None,
  104. url: "tauri://localhost".to_string(),
  105. menu_ids,
  106. }
  107. }
  108. /// Create a new [`PendingWindow`] from a [`WindowConfig`] with a label and starting url.
  109. pub fn with_config(
  110. window_config: WindowConfig,
  111. webview_attributes: WebviewAttributes,
  112. label: impl Into<String>,
  113. ) -> Self {
  114. let window_builder = <<R::Dispatcher as Dispatch>::WindowBuilder>::with_config(window_config);
  115. let mut menu_ids = HashMap::new();
  116. if let Some(menu) = window_builder.get_menu() {
  117. get_menu_ids(&mut menu_ids, menu);
  118. }
  119. Self {
  120. window_builder,
  121. webview_attributes,
  122. uri_scheme_protocols: Default::default(),
  123. label: label.into(),
  124. rpc_handler: None,
  125. file_drop_handler: None,
  126. url: "tauri://localhost".to_string(),
  127. menu_ids,
  128. }
  129. }
  130. pub fn register_uri_scheme_protocol<
  131. N: Into<String>,
  132. H: Fn(&HttpRequest) -> Result<HttpResponse, Box<dyn std::error::Error>> + Send + Sync + 'static,
  133. >(
  134. &mut self,
  135. uri_scheme: N,
  136. protocol: H,
  137. ) {
  138. let uri_scheme = uri_scheme.into();
  139. self
  140. .uri_scheme_protocols
  141. .insert(uri_scheme, Box::new(move |data| (protocol)(data)));
  142. }
  143. }
  144. /// A webview window that is not yet managed by Tauri.
  145. #[derive(Debug)]
  146. pub struct DetachedWindow<R: Runtime> {
  147. /// Name of the window
  148. pub label: String,
  149. /// The [`Dispatch`](crate::Dispatch) associated with the window.
  150. pub dispatcher: R::Dispatcher,
  151. /// Maps runtime id to a string menu id.
  152. pub menu_ids: HashMap<MenuHash, MenuId>,
  153. }
  154. impl<R: Runtime> Clone for DetachedWindow<R> {
  155. fn clone(&self) -> Self {
  156. Self {
  157. label: self.label.clone(),
  158. dispatcher: self.dispatcher.clone(),
  159. menu_ids: self.menu_ids.clone(),
  160. }
  161. }
  162. }
  163. impl<R: Runtime> Hash for DetachedWindow<R> {
  164. /// Only use the [`DetachedWindow`]'s label to represent its hash.
  165. fn hash<H: Hasher>(&self, state: &mut H) {
  166. self.label.hash(state)
  167. }
  168. }
  169. impl<R: Runtime> Eq for DetachedWindow<R> {}
  170. impl<R: Runtime> PartialEq for DetachedWindow<R> {
  171. /// Only use the [`DetachedWindow`]'s label to compare equality.
  172. fn eq(&self, other: &Self) -> bool {
  173. self.label.eq(&other.label)
  174. }
  175. }