use winit::{
dpi::{
LogicalSize,
PhysicalSize,
},
event::Event,
event_loop::{
ControlFlow,
EventLoop,
EventLoopBuilder,
EventLoopProxy,
EventLoopWindowTarget,
},
monitor::MonitorHandle,
window::{
Window,
WindowBuilder,
},
};
pub mod winit_exports {
pub use winit::{
event::{
ElementState,
Event,
MouseButton,
VirtualKeyCode,
WindowEvent,
},
event_loop::{
ControlFlow,
EventLoop,
EventLoopProxy,
EventLoopWindowTarget,
},
};
}
pub struct LoopBuilder;
impl LoopBuilder {
pub fn new() -> Self {
return Self;
}
pub fn build<Events: 'static + std::fmt::Debug>(self) -> Loop<Events> {
let event_loop = EventLoopBuilder::<Events>::with_user_event().build();
return Loop { event_loop };
}
}
pub struct Loop<E: 'static + std::fmt::Debug> {
event_loop: EventLoop<E>,
}
pub struct WindowProperties {
pub name: String,
pub dimensions: (u32, u32),
pub monitor_handle: MonitorHandle,
}
#[derive(Clone, Copy)]
pub struct WindowSize {
pub width: u32,
pub height: u32,
pub logical: LogicalSize<u32>,
pub physical: PhysicalSize<u32>,
}
pub struct WindowHandle {
pub window_handle: Window,
pub size: WindowSize,
pub monitor_handle: MonitorHandle,
}
pub struct WindowHandleBuilder {
window_handle: Option<Window>,
size: WindowSize,
monitor_handle: Option<MonitorHandle>,
}
impl WindowHandleBuilder {
pub fn new() -> Self {
let logical: LogicalSize<u32> = [0, 0].into();
let physical = logical.to_physical(1.0);
let size = WindowSize {
width: 0,
height: 0,
logical,
physical,
};
return Self {
window_handle: None,
size,
monitor_handle: None,
};
}
fn with_window_size(
mut self,
window_size: (u32, u32),
scale_factor: f64,
) -> Self {
let logical: LogicalSize<u32> = window_size.into();
let physical: PhysicalSize<u32> = logical.to_physical(scale_factor);
let (width, height) = window_size;
let window_size = WindowSize {
width,
height,
logical,
physical,
};
self.size = window_size;
return self;
}
pub fn with_window_properties<E: 'static + std::fmt::Debug>(
mut self,
window_properties: WindowProperties,
lambda_loop: &Loop<E>,
) -> Self {
let WindowProperties {
name,
dimensions,
monitor_handle,
} = window_properties;
self = self.with_window_size(dimensions, monitor_handle.scale_factor());
let window_handle = WindowBuilder::new()
.with_title(name)
.with_inner_size(self.size.logical)
.build(&lambda_loop.event_loop)
.expect("Failed creation of window handle");
self.monitor_handle = Some(monitor_handle);
self.window_handle = Some(window_handle);
return self;
}
pub fn build(self) -> WindowHandle {
return WindowHandle {
monitor_handle: self
.monitor_handle
.expect("Unable to find a MonitorHandle."),
size: self.size,
window_handle: self.window_handle.expect("Unable to find WindowHandle."),
};
}
}
pub struct LoopPublisher<E: 'static> {
winit_proxy: EventLoopProxy<E>,
}
impl<E: 'static + std::fmt::Debug> LoopPublisher<E> {
#[inline]
pub fn new(lambda_loop: &Loop<E>) -> Self {
let winit_proxy = lambda_loop.event_loop.create_proxy();
return LoopPublisher { winit_proxy };
}
#[inline]
pub fn publish_event(&self, event: E) {
self
.winit_proxy
.send_event(event)
.expect("Failed to send event");
}
}
impl<E: 'static + std::fmt::Debug> Loop<E> {
pub fn create_event_publisher(&mut self) -> LoopPublisher<E> {
return LoopPublisher::new(&self);
}
pub fn get_primary_monitor(&self) -> Option<MonitorHandle> {
return self.event_loop.primary_monitor();
}
pub fn get_all_monitors(&self) -> impl Iterator<Item = MonitorHandle> {
return self.event_loop.available_monitors();
}
pub fn get_any_available_monitors(&self) -> Option<MonitorHandle> {
return self.event_loop.available_monitors().next();
}
pub fn run_forever<Callback>(self, callback: Callback)
where
Callback: 'static
+ FnMut(Event<E>, &EventLoopWindowTarget<E>, &mut ControlFlow) -> (),
{
self.event_loop.run(callback);
}
}