use std::sync::{Arc, Mutex, RwLock};
use crate::application::prelude::{LifecycleListener, LifecycleListenerHandle};
use crate::errors::*;
use crate::math::prelude::Vector2;
use crate::utils::object_pool::ObjectPool;
use super::backends::{self, Visitor};
use super::events::Event;
use super::WindowParams;
impl_handle!(EventListenerHandle);
pub trait EventListener {
fn on(&mut self, v: &Event) -> Result<()>;
}
pub struct WindowSystem {
lis: LifecycleListenerHandle,
state: Arc<WindowState>,
}
struct WindowState {
visitor: RwLock<Box<dyn Visitor>>,
events: Mutex<Vec<Event>>,
last_frame_listeners: Mutex<Vec<Arc<Mutex<dyn EventListener>>>>,
listeners: Mutex<ObjectPool<EventListenerHandle, Arc<Mutex<dyn EventListener>>>>,
}
impl LifecycleListener for Arc<WindowState> {
fn on_pre_update(&mut self) -> crate::errors::Result<()> {
let mut events = self.events.lock().unwrap();
events.clear();
let mut visitor = self.visitor.write().unwrap();
visitor.poll_events(&mut events);
let mut last_frame_listeners = self.last_frame_listeners.lock().unwrap();
{
let listeners = self.listeners.lock().unwrap();
last_frame_listeners.clear();
last_frame_listeners.extend(listeners.values().cloned());
}
for lis in last_frame_listeners.iter() {
let mut lis = lis.lock().unwrap();
for v in events.iter() {
lis.on(v)?;
}
}
Ok(())
}
fn on_post_update(&mut self) -> crate::errors::Result<()> {
self.visitor.read().unwrap().swap_buffers()?;
Ok(())
}
}
impl Drop for WindowSystem {
fn drop(&mut self) {
crate::application::detach(self.lis);
}
}
impl WindowSystem {
pub fn from(params: WindowParams) -> Result<Self> {
let state = Arc::new(WindowState {
last_frame_listeners: Mutex::new(Vec::new()),
listeners: Mutex::new(ObjectPool::new()),
events: Mutex::new(Vec::new()),
visitor: RwLock::new(backends::new(params)?),
});
let window = WindowSystem {
state: state.clone(),
lis: crate::application::attach(state),
};
Ok(window)
}
pub fn headless() -> Self {
let state = Arc::new(WindowState {
last_frame_listeners: Mutex::new(Vec::new()),
listeners: Mutex::new(ObjectPool::new()),
events: Mutex::new(Vec::new()),
visitor: RwLock::new(backends::new_headless()),
});
WindowSystem {
state: state.clone(),
lis: crate::application::attach(state),
}
}
pub fn add_event_listener<T: EventListener + 'static>(&self, lis: T) -> EventListenerHandle {
let lis = Arc::new(Mutex::new(lis));
self.state.listeners.lock().unwrap().create(lis)
}
pub fn remove_event_listener(&self, handle: EventListenerHandle) {
self.state.listeners.lock().unwrap().free(handle);
}
#[inline]
pub fn show(&self) {
self.state.visitor.read().unwrap().show();
}
#[inline]
pub fn hide(&self) {
self.state.visitor.read().unwrap().hide();
}
#[inline]
pub fn make_current(&self) -> Result<()> {
self.state.visitor.read().unwrap().make_current()
}
#[inline]
pub fn is_current(&self) -> bool {
self.state.visitor.read().unwrap().is_current()
}
#[inline]
pub fn position(&self) -> Vector2<i32> {
self.state.visitor.read().unwrap().position()
}
#[inline]
pub fn dimensions(&self) -> Vector2<u32> {
self.state.visitor.read().unwrap().dimensions()
}
#[inline]
pub fn device_pixel_ratio(&self) -> f32 {
self.state.visitor.read().unwrap().device_pixel_ratio()
}
#[inline]
pub fn resize(&self, dimensions: Vector2<u32>) {
self.state.visitor.read().unwrap().resize(dimensions);
}
}