use std::path::PathBuf;
use pyo3::{
prelude::*,
types::{PyBool, PyFloat, PyInt, PyList, PyString},
BoundObject as _, IntoPyObject,
};
use pyo3_utils::py_wrapper::{PyWrapper, PyWrapperT0};
use crate::ext_mod::{
menu::MenuEvent, tray::TrayIconEvent, PhysicalPositionF64, PhysicalPositionI32,
PhysicalSizeU32, Theme,
};
#[pyclass(frozen)]
#[non_exhaustive]
pub enum RunEvent {
Exit(),
#[non_exhaustive]
ExitRequested {
code: Option<Py<PyInt>>,
api: Py<ExitRequestApi>,
},
#[non_exhaustive]
WindowEvent {
label: Py<PyString>,
event: Py<WindowEvent>,
},
#[non_exhaustive]
WebviewEvent {
label: Py<PyString>,
event: Py<WebviewEvent>,
},
Ready(),
Resumed(),
MainEventsCleared(),
MenuEvent(Py<MenuEvent>),
TrayIconEvent(Py<TrayIconEvent>),
_NonExhaustive(),
}
impl RunEvent {
pub(crate) fn from_tauri(py: Python<'_>, value: tauri::RunEvent) -> PyResult<Self> {
let ret = match value {
tauri::RunEvent::Exit => Self::Exit(),
tauri::RunEvent::ExitRequested { code, api, .. } => {
let code = code.map(|code| {
let Ok(code) = code.into_pyobject(py);
code.unbind()
});
let api = ExitRequestApi::new(api).into_pyobject(py)?.unbind();
Self::ExitRequested { code, api }
}
tauri::RunEvent::WindowEvent { label, event, .. } => Self::WindowEvent {
label: PyString::intern(py, &label).unbind(),
event: WindowEvent::from_tauri(py, &event)?
.into_pyobject(py)?
.unbind(),
},
tauri::RunEvent::WebviewEvent { label, event, .. } => Self::WebviewEvent {
label: PyString::intern(py, &label).unbind(),
event: WebviewEvent::from_tauri(py, &event)?
.into_pyobject(py)?
.unbind(),
},
tauri::RunEvent::Ready => Self::Ready(),
tauri::RunEvent::Resumed => Self::Resumed(),
tauri::RunEvent::MainEventsCleared => Self::MainEventsCleared(),
tauri::RunEvent::MenuEvent(event) => {
Self::MenuEvent(MenuEvent::intern(py, &event.id.0).unbind())
}
tauri::RunEvent::TrayIconEvent(event) => Self::TrayIconEvent(
TrayIconEvent::from_tauri(py, &event)?
.into_pyobject(py)?
.unbind(),
),
_ => Self::_NonExhaustive(),
};
Ok(ret)
}
}
#[pyclass(frozen)]
#[non_exhaustive]
pub struct CloseRequestApi(pub PyWrapper<PyWrapperT0<tauri::CloseRequestApi>>);
impl CloseRequestApi {
fn new(value: tauri::CloseRequestApi) -> Self {
Self(PyWrapper::new0(value))
}
}
#[pymethods]
impl CloseRequestApi {
fn prevent_close(&self) {
self.0.inner_ref().prevent_close();
}
}
#[pyclass(frozen)]
#[non_exhaustive]
pub struct ExitRequestApi(pub PyWrapper<PyWrapperT0<tauri::ExitRequestApi>>);
impl ExitRequestApi {
fn new(value: tauri::ExitRequestApi) -> Self {
Self(PyWrapper::new0(value))
}
}
#[pymethods]
impl ExitRequestApi {
fn prevent_exit(&self) {
self.0.inner_ref().prevent_exit();
}
}
#[derive(FromPyObject, IntoPyObject, IntoPyObjectRef)]
#[pyo3(transparent)]
struct VecPathBuf(Py<PyList>);
impl VecPathBuf {
#[inline]
fn from_tauri(py: Python<'_>, paths: &Vec<PathBuf>) -> PyResult<Self> {
let lst = PyList::new(py, paths)?;
Ok(Self(lst.unbind()))
}
}
#[pyclass(frozen)]
#[non_exhaustive]
pub enum DragDropEvent {
Enter {
#[expect(private_interfaces)]
paths: VecPathBuf,
#[expect(private_interfaces)]
position: PhysicalPositionF64,
},
Over {
#[expect(private_interfaces)]
position: PhysicalPositionF64,
},
Drop {
#[expect(private_interfaces)]
paths: VecPathBuf,
#[expect(private_interfaces)]
position: PhysicalPositionF64,
},
Leave(),
_NonExhaustive(),
}
impl DragDropEvent {
fn from_tauri(py: Python<'_>, value: &tauri::DragDropEvent) -> PyResult<Self> {
let ret = match value {
tauri::DragDropEvent::Enter { paths, position } => Self::Enter {
paths: VecPathBuf::from_tauri(py, paths)?,
position: PhysicalPositionF64::from_tauri(py, *position)?,
},
tauri::DragDropEvent::Over { position } => Self::Over {
position: PhysicalPositionF64::from_tauri(py, *position)?,
},
tauri::DragDropEvent::Drop { paths, position } => Self::Drop {
paths: VecPathBuf::from_tauri(py, paths)?,
position: PhysicalPositionF64::from_tauri(py, *position)?,
},
tauri::DragDropEvent::Leave => Self::Leave(),
_ => Self::_NonExhaustive(),
};
Ok(ret)
}
}
#[pyclass(frozen)]
#[non_exhaustive]
pub enum WebviewEvent {
DragDrop(Py<DragDropEvent>),
_NonExhaustive(),
}
impl WebviewEvent {
pub(crate) fn from_tauri(py: Python<'_>, value: &tauri::WebviewEvent) -> PyResult<Self> {
let ret = match value {
tauri::WebviewEvent::DragDrop(event) => Self::DragDrop(
DragDropEvent::from_tauri(py, event)?
.into_pyobject(py)?
.unbind(),
),
_ => Self::_NonExhaustive(),
};
Ok(ret)
}
}
#[pyclass(frozen)]
#[non_exhaustive]
pub enum WindowEvent {
#[expect(private_interfaces)]
Resized(PhysicalSizeU32),
#[expect(private_interfaces)]
Moved(PhysicalPositionI32),
#[non_exhaustive]
CloseRequested {
api: Py<CloseRequestApi>,
},
Destroyed(),
Focused(Py<PyBool>),
#[non_exhaustive]
ScaleFactorChanged {
scale_factor: Py<PyFloat>,
#[expect(private_interfaces)]
new_inner_size: PhysicalSizeU32,
},
DragDrop(Py<DragDropEvent>),
ThemeChanged(Py<Theme>),
_NonExhaustive(),
}
impl WindowEvent {
pub(crate) fn from_tauri(py: Python<'_>, value: &tauri::WindowEvent) -> PyResult<Self> {
let ret = match value {
tauri::WindowEvent::Resized(size) => {
Self::Resized(PhysicalSizeU32::from_tauri(py, *size)?)
}
tauri::WindowEvent::Moved(pos) => {
Self::Moved(PhysicalPositionI32::from_tauri(py, *pos)?)
}
tauri::WindowEvent::CloseRequested { api, .. } => {
let api = CloseRequestApi::new(api.clone())
.into_pyobject(py)?
.unbind();
Self::CloseRequested { api }
}
tauri::WindowEvent::Destroyed => Self::Destroyed(),
tauri::WindowEvent::Focused(focused) => {
Self::Focused(PyBool::new(py, *focused).unbind())
}
tauri::WindowEvent::ScaleFactorChanged {
scale_factor,
new_inner_size,
..
} => Self::ScaleFactorChanged {
scale_factor: PyFloat::new(py, *scale_factor).unbind(),
new_inner_size: PhysicalSizeU32::from_tauri(py, *new_inner_size)?,
},
tauri::WindowEvent::DragDrop(event) => Self::DragDrop(
DragDropEvent::from_tauri(py, event)?
.into_pyobject(py)?
.unbind(),
),
tauri::WindowEvent::ThemeChanged(theme) => {
Self::ThemeChanged(Theme::from(*theme).into_pyobject(py)?.unbind())
}
_ => Self::_NonExhaustive(),
};
Ok(ret)
}
}