pytauri_core/ext_mod_impl/lib/
manager.rs1use std::{collections::HashMap, iter::Iterator};
2
3use pyo3::{marker::Ungil, prelude::*, FromPyObject, IntoPyObject};
4use pyo3_utils::ungil::UnsafeUngilExt;
5use tauri::Manager as _;
6
7use crate::{
8 ext_mod::{
9 path::PathResolver,
10 webview::{TauriWebviewWindow, WebviewWindow},
11 App, AppHandle, PyAppHandleExt, TauriApp, TauriAppHandle,
12 },
13 tauri_runtime::Runtime,
14};
15
16#[derive(FromPyObject, IntoPyObject, IntoPyObjectRef)]
18#[non_exhaustive]
19pub enum ImplManager {
21 App(Py<App>),
22 AppHandle(Py<AppHandle>),
23 WebviewWindow(Py<WebviewWindow>),
24}
25
26impl ImplManager {
27 #[inline]
28 pub(crate) fn _delegate_app<'py, R>(
29 py: Python<'py>,
30 app: &Py<App>,
31 f: impl FnOnce(Python<'py>, &TauriApp) -> R,
32 ) -> PyResult<R> {
33 let py_app = app.borrow(py);
34 let rs_app = py_app.0.try_lock_inner_ref()??;
35 Ok(f(py, &rs_app))
36 }
37
38 #[inline]
39 pub(crate) fn _delegate_app_handle<'py, R>(
40 py: Python<'py>,
41 app_handle: &Py<AppHandle>,
42 f: impl FnOnce(Python<'py>, &TauriAppHandle) -> R,
43 ) -> PyResult<R> {
44 let app_handle = app_handle.get().0.inner_ref();
45 Ok(f(py, &app_handle))
46 }
47
48 #[inline]
49 pub(crate) fn _delegate_webview_window<'py, R>(
50 py: Python<'py>,
51 webview_window: &Py<WebviewWindow>,
52 f: impl FnOnce(Python<'py>, &TauriWebviewWindow) -> R,
53 ) -> PyResult<R> {
54 let webview_window = webview_window.get().0.inner_ref();
55 Ok(f(py, &webview_window))
56 }
57
58 #[inline]
59 pub(crate) fn _delegate_manager_ungil<M, F, R>(py: Python<'_>, manager: &M, f: F) -> R
60 where
61 M: tauri::Manager<Runtime>,
62 F: FnOnce(&M) -> R + Ungil + Send,
63 R: Ungil,
64 {
65 unsafe {
66 py.allow_threads_unsend(manager, f)
68 }
69 }
70}
71
72macro_rules! manager_method_impl {
90 ($py:expr, $manager:expr, $f0:expr, $f1:expr, $f2:expr) => {{
92 use $crate::ext_mod::ImplManager;
93
94 let manager: &ImplManager = $manager;
95 match manager {
96 ImplManager::App(v) => {
97 ImplManager::_delegate_app($py, v, $f0)
98 }
99 ImplManager::AppHandle(v) => {
100 ImplManager::_delegate_app_handle($py, v, $f1)
101 }
102 ImplManager::WebviewWindow(v) => {
103 ImplManager::_delegate_webview_window($py, v, $f2)
104 }
105 }
106 }};
107
108 ($py:expr, $manager:expr, [ungil], $($f:tt)*) => {{
110 manager_method_impl!($py, $manager, |py, manager| {
111 $crate::ext_mod::ImplManager::_delegate_manager_ungil(py, manager, $($f)*)
112 })
113 }};
114 ($py:expr, $manager:expr, $($f:tt)*) => {
116 manager_method_impl!($py, $manager, $($f)*, $($f)*, $($f)*)
117 };
118}
119
120pub(crate) use manager_method_impl;
122
123#[pyclass(frozen)]
125#[non_exhaustive]
126pub struct Manager;
127
128#[pymethods]
129impl Manager {
130 #[staticmethod]
131 fn app_handle(py: Python<'_>, slf: ImplManager) -> PyResult<Py<AppHandle>> {
132 manager_method_impl!(py, &slf, |py, manager| manager
133 .py_app_handle()
135 .clone_ref(py))
136 }
137
138 #[staticmethod]
139 fn get_webview_window(
140 py: Python<'_>,
141 slf: ImplManager,
142 label: &str,
143 ) -> PyResult<Option<WebviewWindow>> {
144 manager_method_impl!(py, &slf, [ungil], |manager| {
145 manager.get_webview_window(label).map(WebviewWindow::new)
146 })
147 }
148
149 #[staticmethod]
150 fn webview_windows(
151 py: Python<'_>,
152 slf: ImplManager,
153 ) -> PyResult<HashMap<String, WebviewWindow>> {
154 manager_method_impl!(py, &slf, [ungil], |manager| {
155 manager
156 .webview_windows()
157 .into_iter()
158 .map(|(label, window)| (label, WebviewWindow::new(window)))
159 .collect::<_>()
160 })
161 }
162
163 #[staticmethod]
164 fn path(py: Python<'_>, slf: ImplManager) -> PyResult<PathResolver> {
165 manager_method_impl!(py, &slf, [ungil], |manager| {
166 let path_resolver = manager.path().clone();
167 PathResolver::new(path_resolver)
168 })
169 }
170}