mock_runtime.rs 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170
  1. // Copyright 2019-2024 Tauri Programme within The Commons Conservancy
  2. // SPDX-License-Identifier: Apache-2.0
  3. // SPDX-License-Identifier: MIT
  4. #![allow(dead_code)]
  5. #![allow(missing_docs)]
  6. use tauri_runtime::{
  7. dpi::{PhysicalPosition, PhysicalSize, Position, Size},
  8. monitor::Monitor,
  9. webview::{DetachedWebview, PendingWebview},
  10. window::{CursorIcon, DetachedWindow, PendingWindow, RawWindow, WindowEvent, WindowId},
  11. window::{WindowBuilder, WindowBuilderBase},
  12. DeviceEventFilter, Error, EventLoopProxy, ExitRequestedEventAction, Icon, ProgressBarState,
  13. Result, RunEvent, Runtime, RuntimeHandle, RuntimeInitArgs, UserAttentionType, UserEvent,
  14. WebviewDispatch, WindowDispatch, WindowEventId,
  15. };
  16. #[cfg(target_os = "macos")]
  17. use tauri_utils::TitleBarStyle;
  18. use tauri_utils::{config::WindowConfig, Theme};
  19. use url::Url;
  20. #[cfg(windows)]
  21. use windows::Win32::Foundation::HWND;
  22. use std::{
  23. cell::RefCell,
  24. collections::HashMap,
  25. fmt,
  26. sync::{
  27. atomic::{AtomicBool, AtomicU32, Ordering},
  28. mpsc::{channel, sync_channel, Receiver, SyncSender},
  29. Arc, Mutex,
  30. },
  31. };
  32. type ShortcutMap = HashMap<String, Box<dyn Fn() + Send + 'static>>;
  33. enum Message {
  34. Task(Box<dyn FnOnce() + Send>),
  35. CloseWindow(WindowId),
  36. DestroyWindow(WindowId),
  37. }
  38. struct Webview;
  39. struct Window {
  40. label: String,
  41. webviews: Vec<Webview>,
  42. }
  43. #[derive(Clone)]
  44. pub struct RuntimeContext {
  45. is_running: Arc<AtomicBool>,
  46. windows: Arc<RefCell<HashMap<WindowId, Window>>>,
  47. shortcuts: Arc<Mutex<ShortcutMap>>,
  48. run_tx: SyncSender<Message>,
  49. next_window_id: Arc<AtomicU32>,
  50. next_webview_id: Arc<AtomicU32>,
  51. next_window_event_id: Arc<AtomicU32>,
  52. next_webview_event_id: Arc<AtomicU32>,
  53. }
  54. // SAFETY: we ensure this type is only used on the main thread.
  55. #[allow(clippy::non_send_fields_in_send_ty)]
  56. unsafe impl Send for RuntimeContext {}
  57. // SAFETY: we ensure this type is only used on the main thread.
  58. #[allow(clippy::non_send_fields_in_send_ty)]
  59. unsafe impl Sync for RuntimeContext {}
  60. impl RuntimeContext {
  61. fn send_message(&self, message: Message) -> Result<()> {
  62. if self.is_running.load(Ordering::Relaxed) {
  63. self
  64. .run_tx
  65. .send(message)
  66. .map_err(|_| Error::FailedToSendMessage)
  67. } else {
  68. match message {
  69. Message::Task(task) => task(),
  70. Message::CloseWindow(id) | Message::DestroyWindow(id) => {
  71. self.windows.borrow_mut().remove(&id);
  72. }
  73. }
  74. Ok(())
  75. }
  76. }
  77. fn next_window_id(&self) -> WindowId {
  78. self.next_window_id.fetch_add(1, Ordering::Relaxed).into()
  79. }
  80. fn next_webview_id(&self) -> u32 {
  81. self.next_webview_id.fetch_add(1, Ordering::Relaxed)
  82. }
  83. fn next_window_event_id(&self) -> WindowEventId {
  84. self.next_window_event_id.fetch_add(1, Ordering::Relaxed)
  85. }
  86. fn next_webview_event_id(&self) -> WindowEventId {
  87. self.next_webview_event_id.fetch_add(1, Ordering::Relaxed)
  88. }
  89. }
  90. impl fmt::Debug for RuntimeContext {
  91. fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  92. f.debug_struct("RuntimeContext").finish()
  93. }
  94. }
  95. #[derive(Debug, Clone)]
  96. pub struct MockRuntimeHandle {
  97. context: RuntimeContext,
  98. }
  99. impl<T: UserEvent> RuntimeHandle<T> for MockRuntimeHandle {
  100. type Runtime = MockRuntime;
  101. fn create_proxy(&self) -> EventProxy {
  102. EventProxy {}
  103. }
  104. #[cfg(target_os = "macos")]
  105. #[cfg_attr(docsrs, doc(cfg(target_os = "macos")))]
  106. fn set_activation_policy(
  107. &self,
  108. activation_policy: tauri_runtime::ActivationPolicy,
  109. ) -> Result<()> {
  110. Ok(())
  111. }
  112. fn request_exit(&self, code: i32) -> Result<()> {
  113. unimplemented!()
  114. }
  115. /// Create a new webview window.
  116. fn create_window<F: Fn(RawWindow<'_>) + Send + 'static>(
  117. &self,
  118. pending: PendingWindow<T, Self::Runtime>,
  119. _after_window_creation: Option<F>,
  120. ) -> Result<DetachedWindow<T, Self::Runtime>> {
  121. let id = self.context.next_window_id();
  122. let (webview_id, webviews) = if let Some(w) = &pending.webview {
  123. (Some(self.context.next_webview_id()), vec![Webview])
  124. } else {
  125. (None, Vec::new())
  126. };
  127. self.context.windows.borrow_mut().insert(
  128. id,
  129. Window {
  130. label: pending.label.clone(),
  131. webviews,
  132. },
  133. );
  134. let webview = webview_id.map(|id| DetachedWebview {
  135. label: pending.label.clone(),
  136. dispatcher: MockWebviewDispatcher {
  137. id,
  138. context: self.context.clone(),
  139. url: Arc::new(Mutex::new(pending.webview.unwrap().url)),
  140. last_evaluated_script: Default::default(),
  141. },
  142. });
  143. Ok(DetachedWindow {
  144. id,
  145. label: pending.label,
  146. dispatcher: MockWindowDispatcher {
  147. id,
  148. context: self.context.clone(),
  149. },
  150. webview,
  151. })
  152. }
  153. fn create_webview(
  154. &self,
  155. window_id: WindowId,
  156. pending: PendingWebview<T, Self::Runtime>,
  157. ) -> Result<DetachedWebview<T, Self::Runtime>> {
  158. let id = self.context.next_webview_id();
  159. let webview = Webview;
  160. if let Some(w) = self.context.windows.borrow_mut().get_mut(&window_id) {
  161. w.webviews.push(webview);
  162. }
  163. Ok(DetachedWebview {
  164. label: pending.label,
  165. dispatcher: MockWebviewDispatcher {
  166. id,
  167. context: self.context.clone(),
  168. last_evaluated_script: Default::default(),
  169. url: Arc::new(Mutex::new(pending.url)),
  170. },
  171. })
  172. }
  173. /// Run a task on the main thread.
  174. fn run_on_main_thread<F: FnOnce() + Send + 'static>(&self, f: F) -> Result<()> {
  175. self.context.send_message(Message::Task(Box::new(f)))
  176. }
  177. fn display_handle(
  178. &self,
  179. ) -> std::result::Result<raw_window_handle::DisplayHandle<'_>, raw_window_handle::HandleError> {
  180. #[cfg(target_os = "linux")]
  181. return Ok(unsafe {
  182. raw_window_handle::DisplayHandle::borrow_raw(raw_window_handle::RawDisplayHandle::Xlib(
  183. raw_window_handle::XlibDisplayHandle::new(None, 0),
  184. ))
  185. });
  186. #[cfg(target_os = "macos")]
  187. return Ok(unsafe {
  188. raw_window_handle::DisplayHandle::borrow_raw(raw_window_handle::RawDisplayHandle::AppKit(
  189. raw_window_handle::AppKitDisplayHandle::new(),
  190. ))
  191. });
  192. #[cfg(windows)]
  193. return Ok(unsafe {
  194. raw_window_handle::DisplayHandle::borrow_raw(raw_window_handle::RawDisplayHandle::Windows(
  195. raw_window_handle::WindowsDisplayHandle::new(),
  196. ))
  197. });
  198. #[cfg(not(any(target_os = "linux", target_os = "macos", windows)))]
  199. return unimplemented!();
  200. }
  201. fn primary_monitor(&self) -> Option<Monitor> {
  202. unimplemented!()
  203. }
  204. fn monitor_from_point(&self, x: f64, y: f64) -> Option<Monitor> {
  205. unimplemented!()
  206. }
  207. fn available_monitors(&self) -> Vec<Monitor> {
  208. unimplemented!()
  209. }
  210. /// Shows the application, but does not automatically focus it.
  211. #[cfg(target_os = "macos")]
  212. fn show(&self) -> Result<()> {
  213. Ok(())
  214. }
  215. /// Hides the application.
  216. #[cfg(target_os = "macos")]
  217. fn hide(&self) -> Result<()> {
  218. Ok(())
  219. }
  220. #[cfg(target_os = "android")]
  221. fn find_class<'a>(
  222. &self,
  223. env: &mut jni::JNIEnv<'a>,
  224. activity: &jni::objects::JObject<'_>,
  225. name: impl Into<String>,
  226. ) -> std::result::Result<jni::objects::JClass<'a>, jni::errors::Error> {
  227. todo!()
  228. }
  229. #[cfg(target_os = "android")]
  230. fn run_on_android_context<F>(&self, f: F)
  231. where
  232. F: FnOnce(&mut jni::JNIEnv, &jni::objects::JObject, &jni::objects::JObject) + Send + 'static,
  233. {
  234. todo!()
  235. }
  236. fn cursor_position(&self) -> Result<PhysicalPosition<f64>> {
  237. Ok(PhysicalPosition::new(0.0, 0.0))
  238. }
  239. }
  240. #[derive(Debug, Clone)]
  241. pub struct MockWebviewDispatcher {
  242. id: u32,
  243. context: RuntimeContext,
  244. url: Arc<Mutex<String>>,
  245. last_evaluated_script: Arc<Mutex<Option<String>>>,
  246. }
  247. impl MockWebviewDispatcher {
  248. pub fn last_evaluated_script(&self) -> Option<String> {
  249. self.last_evaluated_script.lock().unwrap().clone()
  250. }
  251. }
  252. #[derive(Debug, Clone)]
  253. pub struct MockWindowDispatcher {
  254. id: WindowId,
  255. context: RuntimeContext,
  256. }
  257. #[derive(Debug, Clone)]
  258. pub struct MockWindowBuilder {}
  259. impl WindowBuilderBase for MockWindowBuilder {}
  260. impl WindowBuilder for MockWindowBuilder {
  261. fn new() -> Self {
  262. Self {}
  263. }
  264. fn with_config(config: &WindowConfig) -> Self {
  265. Self {}
  266. }
  267. fn center(self) -> Self {
  268. self
  269. }
  270. fn position(self, x: f64, y: f64) -> Self {
  271. self
  272. }
  273. fn inner_size(self, min_width: f64, min_height: f64) -> Self {
  274. self
  275. }
  276. fn min_inner_size(self, min_width: f64, min_height: f64) -> Self {
  277. self
  278. }
  279. fn max_inner_size(self, max_width: f64, max_height: f64) -> Self {
  280. self
  281. }
  282. fn resizable(self, resizable: bool) -> Self {
  283. self
  284. }
  285. fn maximizable(self, resizable: bool) -> Self {
  286. self
  287. }
  288. fn minimizable(self, resizable: bool) -> Self {
  289. self
  290. }
  291. fn closable(self, resizable: bool) -> Self {
  292. self
  293. }
  294. fn title<S: Into<String>>(self, title: S) -> Self {
  295. self
  296. }
  297. fn fullscreen(self, fullscreen: bool) -> Self {
  298. self
  299. }
  300. fn focused(self, focused: bool) -> Self {
  301. self
  302. }
  303. fn maximized(self, maximized: bool) -> Self {
  304. self
  305. }
  306. fn visible(self, visible: bool) -> Self {
  307. self
  308. }
  309. #[cfg(any(not(target_os = "macos"), feature = "macos-private-api"))]
  310. #[cfg_attr(
  311. docsrs,
  312. doc(cfg(any(not(target_os = "macos"), feature = "macos-private-api")))
  313. )]
  314. fn transparent(self, transparent: bool) -> Self {
  315. self
  316. }
  317. fn decorations(self, decorations: bool) -> Self {
  318. self
  319. }
  320. fn always_on_bottom(self, always_on_bottom: bool) -> Self {
  321. self
  322. }
  323. fn always_on_top(self, always_on_top: bool) -> Self {
  324. self
  325. }
  326. fn visible_on_all_workspaces(self, visible_on_all_workspaces: bool) -> Self {
  327. self
  328. }
  329. fn content_protected(self, protected: bool) -> Self {
  330. self
  331. }
  332. fn icon(self, icon: Icon<'_>) -> Result<Self> {
  333. Ok(self)
  334. }
  335. fn skip_taskbar(self, skip: bool) -> Self {
  336. self
  337. }
  338. fn shadow(self, enable: bool) -> Self {
  339. self
  340. }
  341. #[cfg(windows)]
  342. fn owner(self, owner: HWND) -> Self {
  343. self
  344. }
  345. #[cfg(windows)]
  346. fn parent(self, parent: HWND) -> Self {
  347. self
  348. }
  349. #[cfg(target_os = "macos")]
  350. fn parent(self, parent: *mut std::ffi::c_void) -> Self {
  351. self
  352. }
  353. #[cfg(any(
  354. target_os = "linux",
  355. target_os = "dragonfly",
  356. target_os = "freebsd",
  357. target_os = "netbsd",
  358. target_os = "openbsd"
  359. ))]
  360. fn transient_for(self, parent: &impl gtk::glib::IsA<gtk::Window>) -> Self {
  361. self
  362. }
  363. #[cfg(windows)]
  364. fn drag_and_drop(self, enabled: bool) -> Self {
  365. self
  366. }
  367. #[cfg(target_os = "macos")]
  368. fn title_bar_style(self, style: TitleBarStyle) -> Self {
  369. self
  370. }
  371. #[cfg(target_os = "macos")]
  372. fn hidden_title(self, transparent: bool) -> Self {
  373. self
  374. }
  375. #[cfg(target_os = "macos")]
  376. fn tabbing_identifier(self, identifier: &str) -> Self {
  377. self
  378. }
  379. fn theme(self, theme: Option<Theme>) -> Self {
  380. self
  381. }
  382. fn has_icon(&self) -> bool {
  383. false
  384. }
  385. }
  386. impl<T: UserEvent> WebviewDispatch<T> for MockWebviewDispatcher {
  387. type Runtime = MockRuntime;
  388. fn run_on_main_thread<F: FnOnce() + Send + 'static>(&self, f: F) -> Result<()> {
  389. self.context.send_message(Message::Task(Box::new(f)))
  390. }
  391. fn on_webview_event<F: Fn(&tauri_runtime::window::WebviewEvent) + Send + 'static>(
  392. &self,
  393. f: F,
  394. ) -> tauri_runtime::WebviewEventId {
  395. self.context.next_window_event_id()
  396. }
  397. fn with_webview<F: FnOnce(Box<dyn std::any::Any>) + Send + 'static>(&self, f: F) -> Result<()> {
  398. Ok(())
  399. }
  400. #[cfg(any(debug_assertions, feature = "devtools"))]
  401. fn open_devtools(&self) {}
  402. #[cfg(any(debug_assertions, feature = "devtools"))]
  403. fn close_devtools(&self) {}
  404. #[cfg(any(debug_assertions, feature = "devtools"))]
  405. fn is_devtools_open(&self) -> Result<bool> {
  406. Ok(false)
  407. }
  408. fn set_zoom(&self, scale_factor: f64) -> Result<()> {
  409. Ok(())
  410. }
  411. fn eval_script<S: Into<String>>(&self, script: S) -> Result<()> {
  412. self
  413. .last_evaluated_script
  414. .lock()
  415. .unwrap()
  416. .replace(script.into());
  417. Ok(())
  418. }
  419. fn url(&self) -> Result<String> {
  420. Ok(self.url.lock().unwrap().clone())
  421. }
  422. fn bounds(&self) -> Result<tauri_runtime::Rect> {
  423. Ok(tauri_runtime::Rect::default())
  424. }
  425. fn position(&self) -> Result<PhysicalPosition<i32>> {
  426. Ok(PhysicalPosition { x: 0, y: 0 })
  427. }
  428. fn size(&self) -> Result<PhysicalSize<u32>> {
  429. Ok(PhysicalSize {
  430. width: 0,
  431. height: 0,
  432. })
  433. }
  434. fn navigate(&self, url: Url) -> Result<()> {
  435. *self.url.lock().unwrap() = url.to_string();
  436. Ok(())
  437. }
  438. fn print(&self) -> Result<()> {
  439. Ok(())
  440. }
  441. fn close(&self) -> Result<()> {
  442. Ok(())
  443. }
  444. fn set_bounds(&self, bounds: tauri_runtime::Rect) -> Result<()> {
  445. Ok(())
  446. }
  447. fn set_size(&self, _size: Size) -> Result<()> {
  448. Ok(())
  449. }
  450. fn set_position(&self, _position: Position) -> Result<()> {
  451. Ok(())
  452. }
  453. fn set_focus(&self) -> Result<()> {
  454. Ok(())
  455. }
  456. fn reparent(&self, window_id: WindowId) -> Result<()> {
  457. Ok(())
  458. }
  459. fn set_auto_resize(&self, auto_resize: bool) -> Result<()> {
  460. Ok(())
  461. }
  462. }
  463. impl<T: UserEvent> WindowDispatch<T> for MockWindowDispatcher {
  464. type Runtime = MockRuntime;
  465. type WindowBuilder = MockWindowBuilder;
  466. fn run_on_main_thread<F: FnOnce() + Send + 'static>(&self, f: F) -> Result<()> {
  467. self.context.send_message(Message::Task(Box::new(f)))
  468. }
  469. fn on_window_event<F: Fn(&WindowEvent) + Send + 'static>(&self, f: F) -> WindowEventId {
  470. self.context.next_window_event_id()
  471. }
  472. fn scale_factor(&self) -> Result<f64> {
  473. Ok(1.0)
  474. }
  475. fn inner_position(&self) -> Result<PhysicalPosition<i32>> {
  476. Ok(PhysicalPosition { x: 0, y: 0 })
  477. }
  478. fn outer_position(&self) -> Result<PhysicalPosition<i32>> {
  479. Ok(PhysicalPosition { x: 0, y: 0 })
  480. }
  481. fn inner_size(&self) -> Result<PhysicalSize<u32>> {
  482. Ok(PhysicalSize {
  483. width: 0,
  484. height: 0,
  485. })
  486. }
  487. fn outer_size(&self) -> Result<PhysicalSize<u32>> {
  488. Ok(PhysicalSize {
  489. width: 0,
  490. height: 0,
  491. })
  492. }
  493. fn is_fullscreen(&self) -> Result<bool> {
  494. Ok(false)
  495. }
  496. fn is_minimized(&self) -> Result<bool> {
  497. Ok(false)
  498. }
  499. fn is_maximized(&self) -> Result<bool> {
  500. Ok(false)
  501. }
  502. fn is_focused(&self) -> Result<bool> {
  503. Ok(false)
  504. }
  505. fn is_decorated(&self) -> Result<bool> {
  506. Ok(false)
  507. }
  508. fn is_resizable(&self) -> Result<bool> {
  509. Ok(false)
  510. }
  511. fn is_maximizable(&self) -> Result<bool> {
  512. Ok(true)
  513. }
  514. fn is_minimizable(&self) -> Result<bool> {
  515. Ok(true)
  516. }
  517. fn is_closable(&self) -> Result<bool> {
  518. Ok(true)
  519. }
  520. fn is_visible(&self) -> Result<bool> {
  521. Ok(true)
  522. }
  523. fn title(&self) -> Result<String> {
  524. Ok(String::new())
  525. }
  526. fn current_monitor(&self) -> Result<Option<Monitor>> {
  527. Ok(None)
  528. }
  529. fn primary_monitor(&self) -> Result<Option<Monitor>> {
  530. Ok(None)
  531. }
  532. fn monitor_from_point(&self, x: f64, y: f64) -> Result<Option<Monitor>> {
  533. Ok(None)
  534. }
  535. fn available_monitors(&self) -> Result<Vec<Monitor>> {
  536. Ok(Vec::new())
  537. }
  538. fn theme(&self) -> Result<Theme> {
  539. Ok(Theme::Light)
  540. }
  541. #[cfg(any(
  542. target_os = "linux",
  543. target_os = "dragonfly",
  544. target_os = "freebsd",
  545. target_os = "netbsd",
  546. target_os = "openbsd"
  547. ))]
  548. fn gtk_window(&self) -> Result<gtk::ApplicationWindow> {
  549. unimplemented!()
  550. }
  551. #[cfg(any(
  552. target_os = "linux",
  553. target_os = "dragonfly",
  554. target_os = "freebsd",
  555. target_os = "netbsd",
  556. target_os = "openbsd"
  557. ))]
  558. fn default_vbox(&self) -> Result<gtk::Box> {
  559. unimplemented!()
  560. }
  561. fn window_handle(
  562. &self,
  563. ) -> std::result::Result<raw_window_handle::WindowHandle<'_>, raw_window_handle::HandleError> {
  564. #[cfg(target_os = "linux")]
  565. return unsafe {
  566. Ok(raw_window_handle::WindowHandle::borrow_raw(
  567. raw_window_handle::RawWindowHandle::Xlib(raw_window_handle::XlibWindowHandle::new(0)),
  568. ))
  569. };
  570. #[cfg(target_os = "macos")]
  571. return unsafe {
  572. Ok(raw_window_handle::WindowHandle::borrow_raw(
  573. raw_window_handle::RawWindowHandle::AppKit(raw_window_handle::AppKitWindowHandle::new(
  574. std::ptr::NonNull::from(&()).cast(),
  575. )),
  576. ))
  577. };
  578. #[cfg(windows)]
  579. return unsafe {
  580. Ok(raw_window_handle::WindowHandle::borrow_raw(
  581. raw_window_handle::RawWindowHandle::Win32(raw_window_handle::Win32WindowHandle::new(
  582. std::num::NonZeroIsize::MIN,
  583. )),
  584. ))
  585. };
  586. #[cfg(not(any(target_os = "linux", target_os = "macos", windows)))]
  587. return unimplemented!();
  588. }
  589. fn center(&self) -> Result<()> {
  590. Ok(())
  591. }
  592. fn request_user_attention(&self, request_type: Option<UserAttentionType>) -> Result<()> {
  593. Ok(())
  594. }
  595. fn create_window<F: Fn(RawWindow<'_>) + Send + 'static>(
  596. &mut self,
  597. pending: PendingWindow<T, Self::Runtime>,
  598. _after_window_creation: Option<F>,
  599. ) -> Result<DetachedWindow<T, Self::Runtime>> {
  600. let id = self.context.next_window_id();
  601. let (webview_id, webviews) = if let Some(w) = &pending.webview {
  602. (Some(self.context.next_webview_id()), vec![Webview])
  603. } else {
  604. (None, Vec::new())
  605. };
  606. self.context.windows.borrow_mut().insert(
  607. id,
  608. Window {
  609. label: pending.label.clone(),
  610. webviews,
  611. },
  612. );
  613. let webview = webview_id.map(|id| DetachedWebview {
  614. label: pending.label.clone(),
  615. dispatcher: MockWebviewDispatcher {
  616. id,
  617. context: self.context.clone(),
  618. url: Arc::new(Mutex::new(pending.webview.unwrap().url)),
  619. last_evaluated_script: Default::default(),
  620. },
  621. });
  622. Ok(DetachedWindow {
  623. id,
  624. label: pending.label,
  625. dispatcher: MockWindowDispatcher {
  626. id,
  627. context: self.context.clone(),
  628. },
  629. webview,
  630. })
  631. }
  632. fn create_webview(
  633. &mut self,
  634. pending: PendingWebview<T, Self::Runtime>,
  635. ) -> Result<DetachedWebview<T, Self::Runtime>> {
  636. let id = self.context.next_webview_id();
  637. let webview = Webview;
  638. if let Some(w) = self.context.windows.borrow_mut().get_mut(&self.id) {
  639. w.webviews.push(webview);
  640. }
  641. Ok(DetachedWebview {
  642. label: pending.label,
  643. dispatcher: MockWebviewDispatcher {
  644. id,
  645. context: self.context.clone(),
  646. last_evaluated_script: Default::default(),
  647. url: Arc::new(Mutex::new(pending.url)),
  648. },
  649. })
  650. }
  651. fn set_resizable(&self, resizable: bool) -> Result<()> {
  652. Ok(())
  653. }
  654. fn set_maximizable(&self, maximizable: bool) -> Result<()> {
  655. Ok(())
  656. }
  657. fn set_minimizable(&self, minimizable: bool) -> Result<()> {
  658. Ok(())
  659. }
  660. fn set_closable(&self, closable: bool) -> Result<()> {
  661. Ok(())
  662. }
  663. fn set_title<S: Into<String>>(&self, title: S) -> Result<()> {
  664. Ok(())
  665. }
  666. fn maximize(&self) -> Result<()> {
  667. Ok(())
  668. }
  669. fn unmaximize(&self) -> Result<()> {
  670. Ok(())
  671. }
  672. fn minimize(&self) -> Result<()> {
  673. Ok(())
  674. }
  675. fn unminimize(&self) -> Result<()> {
  676. Ok(())
  677. }
  678. fn show(&self) -> Result<()> {
  679. Ok(())
  680. }
  681. fn hide(&self) -> Result<()> {
  682. Ok(())
  683. }
  684. fn close(&self) -> Result<()> {
  685. self.context.send_message(Message::CloseWindow(self.id))?;
  686. Ok(())
  687. }
  688. fn destroy(&self) -> Result<()> {
  689. self.context.send_message(Message::DestroyWindow(self.id))?;
  690. Ok(())
  691. }
  692. fn set_decorations(&self, decorations: bool) -> Result<()> {
  693. Ok(())
  694. }
  695. fn set_shadow(&self, shadow: bool) -> Result<()> {
  696. Ok(())
  697. }
  698. fn set_always_on_bottom(&self, always_on_bottom: bool) -> Result<()> {
  699. Ok(())
  700. }
  701. fn set_always_on_top(&self, always_on_top: bool) -> Result<()> {
  702. Ok(())
  703. }
  704. fn set_visible_on_all_workspaces(&self, visible_on_all_workspaces: bool) -> Result<()> {
  705. Ok(())
  706. }
  707. fn set_content_protected(&self, protected: bool) -> Result<()> {
  708. Ok(())
  709. }
  710. fn set_size(&self, size: Size) -> Result<()> {
  711. Ok(())
  712. }
  713. fn set_min_size(&self, size: Option<Size>) -> Result<()> {
  714. Ok(())
  715. }
  716. fn set_max_size(&self, size: Option<Size>) -> Result<()> {
  717. Ok(())
  718. }
  719. fn set_position(&self, position: Position) -> Result<()> {
  720. Ok(())
  721. }
  722. fn set_fullscreen(&self, fullscreen: bool) -> Result<()> {
  723. Ok(())
  724. }
  725. fn set_focus(&self) -> Result<()> {
  726. Ok(())
  727. }
  728. fn set_icon(&self, icon: Icon<'_>) -> Result<()> {
  729. Ok(())
  730. }
  731. fn set_skip_taskbar(&self, skip: bool) -> Result<()> {
  732. Ok(())
  733. }
  734. fn set_cursor_grab(&self, grab: bool) -> Result<()> {
  735. Ok(())
  736. }
  737. fn set_cursor_visible(&self, visible: bool) -> Result<()> {
  738. Ok(())
  739. }
  740. fn set_cursor_icon(&self, icon: CursorIcon) -> Result<()> {
  741. Ok(())
  742. }
  743. fn set_cursor_position<Pos: Into<Position>>(&self, position: Pos) -> Result<()> {
  744. Ok(())
  745. }
  746. fn set_ignore_cursor_events(&self, ignore: bool) -> Result<()> {
  747. Ok(())
  748. }
  749. fn start_dragging(&self) -> Result<()> {
  750. Ok(())
  751. }
  752. fn start_resize_dragging(&self, direction: tauri_runtime::ResizeDirection) -> Result<()> {
  753. Ok(())
  754. }
  755. fn set_progress_bar(&self, progress_state: ProgressBarState) -> Result<()> {
  756. Ok(())
  757. }
  758. }
  759. #[derive(Debug, Clone)]
  760. pub struct EventProxy {}
  761. impl<T: UserEvent> EventLoopProxy<T> for EventProxy {
  762. fn send_event(&self, event: T) -> Result<()> {
  763. Ok(())
  764. }
  765. }
  766. #[derive(Debug)]
  767. pub struct MockRuntime {
  768. is_running: Arc<AtomicBool>,
  769. pub context: RuntimeContext,
  770. run_rx: Receiver<Message>,
  771. }
  772. impl MockRuntime {
  773. fn init() -> Self {
  774. let is_running = Arc::new(AtomicBool::new(false));
  775. let (tx, rx) = sync_channel(256);
  776. let context = RuntimeContext {
  777. is_running: is_running.clone(),
  778. windows: Default::default(),
  779. shortcuts: Default::default(),
  780. run_tx: tx,
  781. next_window_id: Default::default(),
  782. next_webview_id: Default::default(),
  783. next_window_event_id: Default::default(),
  784. next_webview_event_id: Default::default(),
  785. };
  786. Self {
  787. is_running,
  788. context,
  789. run_rx: rx,
  790. }
  791. }
  792. }
  793. impl<T: UserEvent> Runtime<T> for MockRuntime {
  794. type WindowDispatcher = MockWindowDispatcher;
  795. type WebviewDispatcher = MockWebviewDispatcher;
  796. type Handle = MockRuntimeHandle;
  797. type EventLoopProxy = EventProxy;
  798. fn new(_args: RuntimeInitArgs) -> Result<Self> {
  799. Ok(Self::init())
  800. }
  801. #[cfg(any(windows, target_os = "linux"))]
  802. fn new_any_thread(_args: RuntimeInitArgs) -> Result<Self> {
  803. Ok(Self::init())
  804. }
  805. fn create_proxy(&self) -> EventProxy {
  806. EventProxy {}
  807. }
  808. fn handle(&self) -> Self::Handle {
  809. MockRuntimeHandle {
  810. context: self.context.clone(),
  811. }
  812. }
  813. fn create_window<F: Fn(RawWindow<'_>) + Send + 'static>(
  814. &self,
  815. pending: PendingWindow<T, Self>,
  816. _after_window_creation: Option<F>,
  817. ) -> Result<DetachedWindow<T, Self>> {
  818. let id = self.context.next_window_id();
  819. let (webview_id, webviews) = if let Some(w) = &pending.webview {
  820. (Some(self.context.next_webview_id()), vec![Webview])
  821. } else {
  822. (None, Vec::new())
  823. };
  824. self.context.windows.borrow_mut().insert(
  825. id,
  826. Window {
  827. label: pending.label.clone(),
  828. webviews,
  829. },
  830. );
  831. let webview = webview_id.map(|id| DetachedWebview {
  832. label: pending.label.clone(),
  833. dispatcher: MockWebviewDispatcher {
  834. id,
  835. context: self.context.clone(),
  836. url: Arc::new(Mutex::new(pending.webview.unwrap().url)),
  837. last_evaluated_script: Default::default(),
  838. },
  839. });
  840. Ok(DetachedWindow {
  841. id,
  842. label: pending.label,
  843. dispatcher: MockWindowDispatcher {
  844. id,
  845. context: self.context.clone(),
  846. },
  847. webview,
  848. })
  849. }
  850. fn create_webview(
  851. &self,
  852. window_id: WindowId,
  853. pending: PendingWebview<T, Self>,
  854. ) -> Result<DetachedWebview<T, Self>> {
  855. let id = self.context.next_webview_id();
  856. let webview = Webview;
  857. if let Some(w) = self.context.windows.borrow_mut().get_mut(&window_id) {
  858. w.webviews.push(webview);
  859. }
  860. Ok(DetachedWebview {
  861. label: pending.label,
  862. dispatcher: MockWebviewDispatcher {
  863. id,
  864. context: self.context.clone(),
  865. last_evaluated_script: Default::default(),
  866. url: Arc::new(Mutex::new(pending.url)),
  867. },
  868. })
  869. }
  870. fn primary_monitor(&self) -> Option<Monitor> {
  871. unimplemented!()
  872. }
  873. fn monitor_from_point(&self, x: f64, y: f64) -> Option<Monitor> {
  874. unimplemented!()
  875. }
  876. fn available_monitors(&self) -> Vec<Monitor> {
  877. unimplemented!()
  878. }
  879. #[cfg(target_os = "macos")]
  880. #[cfg_attr(docsrs, doc(cfg(target_os = "macos")))]
  881. fn set_activation_policy(&mut self, activation_policy: tauri_runtime::ActivationPolicy) {}
  882. #[cfg(target_os = "macos")]
  883. #[cfg_attr(docsrs, doc(cfg(target_os = "macos")))]
  884. fn show(&self) {}
  885. #[cfg(target_os = "macos")]
  886. #[cfg_attr(docsrs, doc(cfg(target_os = "macos")))]
  887. fn hide(&self) {}
  888. fn set_device_event_filter(&mut self, filter: DeviceEventFilter) {}
  889. #[cfg(any(
  890. target_os = "macos",
  891. windows,
  892. target_os = "linux",
  893. target_os = "dragonfly",
  894. target_os = "freebsd",
  895. target_os = "netbsd",
  896. target_os = "openbsd"
  897. ))]
  898. fn run_iteration<F: FnMut(RunEvent<T>)>(&mut self, callback: F) {}
  899. fn run<F: FnMut(RunEvent<T>) + 'static>(self, mut callback: F) {
  900. self.is_running.store(true, Ordering::Relaxed);
  901. callback(RunEvent::Ready);
  902. loop {
  903. if let Ok(m) = self.run_rx.try_recv() {
  904. match m {
  905. Message::Task(p) => p(),
  906. Message::CloseWindow(id) => {
  907. let label = self
  908. .context
  909. .windows
  910. .borrow()
  911. .get(&id)
  912. .map(|w| w.label.clone());
  913. if let Some(label) = label {
  914. let (tx, rx) = channel();
  915. callback(RunEvent::WindowEvent {
  916. label,
  917. event: WindowEvent::CloseRequested { signal_tx: tx },
  918. });
  919. let should_prevent = matches!(rx.try_recv(), Ok(true));
  920. if !should_prevent {
  921. self.context.windows.borrow_mut().remove(&id);
  922. let is_empty = self.context.windows.borrow().is_empty();
  923. if is_empty {
  924. let (tx, rx) = channel();
  925. callback(RunEvent::ExitRequested { code: None, tx });
  926. let recv = rx.try_recv();
  927. let should_prevent = matches!(recv, Ok(ExitRequestedEventAction::Prevent));
  928. if !should_prevent {
  929. break;
  930. }
  931. }
  932. }
  933. }
  934. }
  935. Message::DestroyWindow(id) => {
  936. let removed = self.context.windows.borrow_mut().remove(&id).is_some();
  937. if removed {
  938. let is_empty = self.context.windows.borrow().is_empty();
  939. if is_empty {
  940. let (tx, rx) = channel();
  941. callback(RunEvent::ExitRequested { code: None, tx });
  942. let recv = rx.try_recv();
  943. let should_prevent = matches!(recv, Ok(ExitRequestedEventAction::Prevent));
  944. if !should_prevent {
  945. break;
  946. }
  947. }
  948. }
  949. }
  950. }
  951. }
  952. callback(RunEvent::MainEventsCleared);
  953. std::thread::sleep(std::time::Duration::from_secs(1));
  954. }
  955. callback(RunEvent::Exit);
  956. }
  957. fn cursor_position(&self) -> Result<PhysicalPosition<f64>> {
  958. Ok(PhysicalPosition::new(0.0, 0.0))
  959. }
  960. }