pytauri_core/ext_mod_impl/
window.rs

1use pyo3::{
2    prelude::*,
3    types::{PyDict, PyFloat, PyString},
4};
5use pyo3_utils::{
6    from_py_dict::{derive_from_py_dict, FromPyDict as _, NotRequired},
7    py_wrapper::{PyWrapper, PyWrapperT0},
8};
9use tauri::window;
10
11use crate::{
12    ext_mod::{webview::Color, PhysicalPositionI32, PhysicalRect, PhysicalSizeU32},
13    tauri_runtime::Runtime,
14    utils::non_exhaustive_panic,
15};
16
17type TauriWindow = window::Window<Runtime>;
18
19/// See also: [tauri::window::Window]
20#[pyclass(frozen)]
21#[non_exhaustive]
22pub struct Window(pub PyWrapper<PyWrapperT0<TauriWindow>>);
23
24impl Window {
25    pub(crate) fn new(window: TauriWindow) -> Self {
26        Self(PyWrapper::new0(window))
27    }
28}
29
30/// See also: [tauri::window::Monitor]
31#[pyclass(frozen)]
32#[non_exhaustive]
33pub struct Monitor {
34    #[pyo3(get)]
35    name: Option<Py<PyString>>,
36    #[pyo3(get)]
37    size: PhysicalSizeU32,
38    #[pyo3(get)]
39    position: PhysicalPositionI32,
40    #[pyo3(get)]
41    work_area: Py<PhysicalRect>,
42    #[pyo3(get)]
43    scale_factor: Py<PyFloat>,
44}
45
46impl Monitor {
47    pub(crate) fn from_tauri(py: Python<'_>, monitor: window::Monitor) -> PyResult<Self> {
48        let name = monitor.name().map(|n| PyString::new(py, n).into());
49        let size = PhysicalSizeU32::from_tauri(py, *monitor.size())?;
50        let position = PhysicalPositionI32::from_tauri(py, *monitor.position())?;
51        let work_area = Py::new(py, PhysicalRect::from_tauri(py, *monitor.work_area())?)?;
52        let scale_factor = PyFloat::new(py, monitor.scale_factor()).into();
53        Ok(Self {
54            name,
55            size,
56            position,
57            work_area,
58            scale_factor,
59        })
60    }
61}
62
63macro_rules! effect_impl {
64    ($ident:ident => : $($variant:ident),*) => {
65        /// See also: [tauri::window::Effect]
66        #[pyclass(frozen, eq, eq_int)]
67        #[derive(PartialEq, Clone, Copy)]
68        #[non_exhaustive]
69        pub enum $ident {
70            $($variant,)*
71        }
72
73        impl From<tauri::window::Effect> for $ident {
74            fn from(val: tauri::window::Effect) -> Self {
75                #[expect(deprecated)]
76                match val {
77                    $(tauri::window::Effect::$variant => $ident::$variant,)*
78                }
79            }
80        }
81
82        impl From<$ident> for tauri::window::Effect {
83            fn from(val: $ident) -> Self {
84                #[expect(deprecated)]
85                match val {
86                    $($ident::$variant => tauri::window::Effect::$variant,)*
87                }
88            }
89        }
90    };
91}
92
93effect_impl!(
94    Effect => :
95    AppearanceBased,
96    Light,
97    Dark,
98    MediumLight,
99    UltraDark,
100    Titlebar,
101    Selection,
102    Menu,
103    Popover,
104    Sidebar,
105    HeaderView,
106    Sheet,
107    WindowBackground,
108    HudWindow,
109    FullScreenUI,
110    Tooltip,
111    ContentBackground,
112    UnderWindowBackground,
113    UnderPageBackground,
114    Mica,
115    MicaDark,
116    MicaLight,
117    Tabbed,
118    TabbedDark,
119    TabbedLight,
120    Blur,
121    Acrylic
122);
123
124macro_rules! effect_state_impl {
125    ($ident:ident => : $($variant:ident),*) => {
126        /// See also: [tauri::window::EffectState]
127        #[pyclass(frozen, eq, eq_int)]
128        #[derive(PartialEq, Clone, Copy)]
129        #[non_exhaustive]
130        pub enum $ident {
131            $($variant,)*
132        }
133
134        impl From<tauri::window::EffectState> for $ident {
135            fn from(val: tauri::window::EffectState) -> Self {
136                match val {
137                    $(tauri::window::EffectState::$variant => $ident::$variant,)*
138                }
139            }
140        }
141
142        impl From<$ident> for tauri::window::EffectState {
143            fn from(val: $ident) -> Self {
144                match val {
145                    $($ident::$variant => tauri::window::EffectState::$variant,)*
146                }
147            }
148        }
149    };
150}
151
152effect_state_impl!(EffectState => : FollowsWindowActiveState, Active, Inactive);
153
154/// See also: [tauri::window::EffectsBuilder]
155pub struct Effects {
156    effects: NotRequired<Vec<Effect>>,
157    state: NotRequired<EffectState>,
158    radius: NotRequired<f64>,
159    color: NotRequired<Color>,
160}
161
162derive_from_py_dict!(Effects {
163    #[pyo3(default)]
164    effects,
165    #[pyo3(default)]
166    state,
167    #[pyo3(default)]
168    radius,
169    #[pyo3(default)]
170    color,
171});
172
173impl<'py> FromPyObject<'py> for Effects {
174    fn extract_bound(ob: &Bound<'py, PyAny>) -> PyResult<Self> {
175        let dict = ob.downcast::<PyDict>()?;
176        Self::from_py_dict(dict)
177    }
178}
179
180impl Effects {
181    // NOTE: We do not want to use [tauri::utils::config::WindowEffectsConfig],
182    // because it comes from `tauri_utils` (which may be unstable).
183    pub(crate) fn into_tauri(self) -> window::EffectsBuilder {
184        let mut builder = window::EffectsBuilder::new();
185        let Self {
186            effects,
187            state,
188            radius,
189            color,
190        } = self;
191
192        if let Some(effects) = effects.0 {
193            let effects = effects.into_iter().map(Into::into);
194            builder = builder.effects(effects);
195        }
196        if let Some(state) = state.0 {
197            builder = builder.state(state.into());
198        }
199        if let Some(radius) = radius.0 {
200            builder = builder.radius(radius);
201        }
202        if let Some(color) = color.0 {
203            builder = builder.color(color.0);
204        }
205        builder
206    }
207}
208
209macro_rules! progress_bar_status_impl {
210    ($ident:ident => : $( $(#[$meta:meta])* $variant:ident ),*) => {
211        /// See also: [tauri::window::ProgressBarStatus]
212        #[pyclass(frozen, eq, eq_int)]
213        #[derive(PartialEq, Clone, Copy)]
214        #[non_exhaustive]
215        pub enum $ident {
216            $(
217                $(#[$meta])*
218                $variant,
219            )*
220        }
221
222        impl From<tauri::window::ProgressBarStatus> for $ident {
223            fn from(val: tauri::window::ProgressBarStatus) -> Self {
224                match val {
225                    $(tauri::window::ProgressBarStatus::$variant => $ident::$variant,)*
226                }
227            }
228        }
229
230        impl From<$ident> for tauri::window::ProgressBarStatus {
231            fn from(val: $ident) -> Self {
232                match val {
233                    $($ident::$variant => tauri::window::ProgressBarStatus::$variant,)*
234                }
235            }
236        }
237    };
238}
239
240// See also: [tauri::window::ProgressBarStatus]
241progress_bar_status_impl!(
242    ProgressBarStatus => :
243    #[pyo3(name = "None_")]
244    None,
245    Normal,
246    Indeterminate,
247    Paused,
248    Error
249);
250
251/// See also: [tauri::window::ProgressBarState]
252pub struct ProgressBarState {
253    status: NotRequired<ProgressBarStatus>,
254    progress: NotRequired<u64>,
255}
256
257derive_from_py_dict!(ProgressBarState {
258    #[pyo3(default)]
259    status,
260    #[pyo3(default)]
261    progress,
262});
263
264impl<'py> FromPyObject<'py> for ProgressBarState {
265    fn extract_bound(ob: &Bound<'py, PyAny>) -> PyResult<Self> {
266        let dict = ob.downcast::<PyDict>()?;
267        Self::from_py_dict(dict)
268    }
269}
270
271impl ProgressBarState {
272    pub(crate) fn into_tauri(self) -> window::ProgressBarState {
273        let Self { status, progress } = self;
274
275        let status = status.0.map(Into::into);
276        let progress = progress.0;
277
278        window::ProgressBarState { status, progress }
279    }
280}
281
282macro_rules! title_bar_style_impl {
283    ($ident:ident => : $($variant:ident),*) => {
284        /// See also: [tauri::TitleBarStyle]
285        #[pyclass(frozen, eq, eq_int)]
286        #[derive(PartialEq, Clone, Copy)]
287        #[non_exhaustive]
288        pub enum $ident {
289            $($variant,)*
290            _NonExhaustive,
291        }
292
293        impl From<tauri::TitleBarStyle> for $ident {
294            fn from(val: tauri::TitleBarStyle) -> Self {
295                match val {
296                    $(tauri::TitleBarStyle::$variant => $ident::$variant,)*
297                    _ => { $ident::_NonExhaustive }
298                }
299            }
300        }
301
302        impl From<$ident> for tauri::TitleBarStyle {
303            fn from(val: $ident) -> Self {
304                match val {
305                    $($ident::$variant => tauri::TitleBarStyle::$variant,)*
306                    $ident::_NonExhaustive => non_exhaustive_panic(),
307                }
308            }
309        }
310    };
311}
312
313title_bar_style_impl!(
314    TitleBarStyle => :
315    Visible,
316    Transparent,
317    Overlay
318);