#![expect(
unsafe_code,
reason = "This module acts as a wrapper around the `raw_window_handle` crate, which exposes many unsafe interfaces; thus, we have to use unsafe code here."
)]
use alloc::sync::Arc;
use bevy_ecs::prelude::Component;
use bevy_platform::sync::Mutex;
use core::{any::Any, marker::PhantomData, ops::Deref};
use raw_window_handle::{
DisplayHandle, HandleError, HasDisplayHandle, HasWindowHandle, RawDisplayHandle,
RawWindowHandle, WindowHandle,
};
#[derive(Debug)]
pub struct WindowWrapper<W> {
reference: Arc<dyn Any + Send + Sync>,
ty: PhantomData<W>,
}
impl<W: Send + Sync + 'static> WindowWrapper<W> {
pub fn new(window: W) -> WindowWrapper<W> {
WindowWrapper {
reference: Arc::new(window),
ty: PhantomData,
}
}
}
impl<W: 'static> Deref for WindowWrapper<W> {
type Target = W;
fn deref(&self) -> &Self::Target {
self.reference.downcast_ref::<W>().unwrap()
}
}
#[derive(Debug, Clone, Component)]
pub struct RawHandleWrapper {
_window: Arc<dyn Any + Send + Sync>,
window_handle: RawWindowHandle,
display_handle: RawDisplayHandle,
}
impl RawHandleWrapper {
pub fn new<W: HasWindowHandle + HasDisplayHandle + 'static>(
window: &WindowWrapper<W>,
) -> Result<RawHandleWrapper, HandleError> {
Ok(RawHandleWrapper {
_window: window.reference.clone(),
window_handle: window.window_handle()?.as_raw(),
display_handle: window.display_handle()?.as_raw(),
})
}
pub unsafe fn get_handle(&self) -> ThreadLockedRawWindowHandleWrapper {
ThreadLockedRawWindowHandleWrapper(self.clone())
}
pub fn get_window_handle(&self) -> RawWindowHandle {
self.window_handle
}
pub unsafe fn set_window_handle(&mut self, window_handle: RawWindowHandle) -> &mut Self {
self.window_handle = window_handle;
self
}
pub fn get_display_handle(&self) -> RawDisplayHandle {
self.display_handle
}
pub fn set_display_handle(&mut self, display_handle: RawDisplayHandle) -> &mut Self {
self.display_handle = display_handle;
self
}
}
unsafe impl Send for RawHandleWrapper {}
unsafe impl Sync for RawHandleWrapper {}
pub struct ThreadLockedRawWindowHandleWrapper(RawHandleWrapper);
impl HasWindowHandle for ThreadLockedRawWindowHandleWrapper {
fn window_handle(&self) -> Result<WindowHandle<'_>, HandleError> {
Ok(unsafe { WindowHandle::borrow_raw(self.0.window_handle) })
}
}
impl HasDisplayHandle for ThreadLockedRawWindowHandleWrapper {
fn display_handle(&self) -> Result<DisplayHandle<'_>, HandleError> {
Ok(unsafe { DisplayHandle::borrow_raw(self.0.display_handle) })
}
}
#[derive(Debug, Clone, Component)]
pub struct RawHandleWrapperHolder(pub Arc<Mutex<Option<RawHandleWrapper>>>);