use std::any::Any;
use std::fmt::Debug;
use std::ops::Deref;
use std::path::PathBuf;
use std::sync::{Arc, Mutex};
use winit::dpi::{PhysicalPosition, PhysicalSize};
use winit::event::{AxisId, DeviceEvent, DeviceId, ElementState, KeyboardInput, ModifiersState, MouseButton, MouseScrollDelta, StartCause, Touch, TouchPhase};
use winit::window::{Theme, WindowId};
#[derive(Debug, Clone, PartialEq)]
pub enum Event {
NewEvents(StartCause),
WindowEvent {
window_id: WindowId,
event: WindowEvent,
},
DeviceEvent {
device_id: DeviceId,
event: DeviceEvent,
},
UserEvent(UserEvent),
Suspended,
Resumed,
MainEventsCleared,
RedrawRequested(WindowId),
RedrawEventsCleared,
LoopDestroyed,
}
#[derive(Debug, Clone, PartialEq)]
pub enum WindowEvent {
Resized(PhysicalSize<u32>),
Moved(PhysicalPosition<i32>),
CloseRequested,
Destroyed,
DroppedFile(PathBuf),
HoveredFile(PathBuf),
HoveredFileCancelled,
ReceivedCharacter(char),
Focused(bool),
KeyboardInput {
device_id: DeviceId,
input: KeyboardInput,
is_synthetic: bool,
},
ModifiersChanged(ModifiersState),
CursorMoved {
device_id: DeviceId,
position: PhysicalPosition<f64>,
#[deprecated = "Deprecated in favor of WindowEvent::ModifiersChanged"]
modifiers: ModifiersState,
},
CursorEntered { device_id: DeviceId },
CursorLeft { device_id: DeviceId },
MouseWheel {
device_id: DeviceId,
delta: MouseScrollDelta,
phase: TouchPhase,
#[deprecated = "Deprecated in favor of WindowEvent::ModifiersChanged"]
modifiers: ModifiersState,
},
MouseInput {
device_id: DeviceId,
state: ElementState,
button: MouseButton,
#[deprecated = "Deprecated in favor of WindowEvent::ModifiersChanged"]
modifiers: ModifiersState,
},
TouchpadPressure {
device_id: DeviceId,
pressure: f32,
stage: i64,
},
AxisMotion {
device_id: DeviceId,
axis: AxisId,
value: f64,
},
Touch(Touch),
ScaleFactorChanged {
scale_factor: f64,
new_inner_size: NewInnerSize,
},
ThemeChanged(Theme),
}
#[derive(Debug, Clone)]
#[doc(hidden)]
pub struct NewInnerSize(Arc<Mutex<PhysicalSize<u32>>>);
impl Deref for NewInnerSize {
type Target = Mutex<PhysicalSize<u32>>;
fn deref(&self) -> &Self::Target {
self.0.deref()
}
}
impl PartialEq for NewInnerSize {
fn eq(&self, _other: &Self) -> bool {
true
}
}
#[derive(Debug, Clone)]
pub enum UserEvent {
Primitive(usize),
Box(Box<dyn UserEventTrait>),
}
pub trait UserEventTrait: Any + Debug + Send {
fn rough_eq(&self, other: &dyn UserEventTrait) -> bool;
fn clone(&self) -> Box<dyn UserEventTrait>;
}
impl Clone for Box<dyn UserEventTrait> {
fn clone(&self) -> Self {
UserEventTrait::clone(self.as_ref())
}
}
impl PartialEq for Box<dyn UserEventTrait> {
fn eq(&self, other: &Self) -> bool {
UserEventTrait::rough_eq(self.as_ref(), other.as_ref())
}
}
impl PartialEq for UserEvent {
fn eq(&self, other: &Self) -> bool {
match (self, other) {
(UserEvent::Primitive(a), UserEvent::Primitive(b)) => a == b,
(UserEvent::Box(a), UserEvent::Box(b)) => a.eq(b),
_ => false,
}
}
}
#[allow(deprecated)]
impl Event {
pub fn from(event: winit::event::Event<'_, UserEvent>) -> (Self, Option<&mut PhysicalSize<u32>>) {
match event {
winit::event::Event::NewEvents(x) => (Event::NewEvents(x.clone()), None),
winit::event::Event::WindowEvent { window_id, event } => {
let (event, physical_size) = WindowEvent::from(event);
(Event::WindowEvent { window_id: window_id.clone(), event }, physical_size)
},
winit::event::Event::DeviceEvent { device_id, event } => (Event::DeviceEvent { device_id: device_id.clone(), event: event.clone() }, None),
winit::event::Event::UserEvent(x) => (Event::UserEvent(x.clone()), None),
winit::event::Event::Suspended => (Event::Suspended, None),
winit::event::Event::Resumed => (Event::Resumed, None),
winit::event::Event::MainEventsCleared => (Event::MainEventsCleared, None),
winit::event::Event::RedrawRequested(x) => (Event::RedrawRequested(x.clone()), None),
winit::event::Event::RedrawEventsCleared => (Event::RedrawEventsCleared, None),
winit::event::Event::LoopDestroyed => (Event::LoopDestroyed, None)
}
}
pub fn into(self, physical_size: Option<&mut PhysicalSize<u32>>) -> winit::event::Event<'_, UserEvent> {
match self {
Event::NewEvents(x) => winit::event::Event::NewEvents(x),
Event::WindowEvent { window_id, event } => {
let event = event.into(physical_size);
winit::event::Event::WindowEvent { window_id, event }
}
Event::DeviceEvent { device_id, event } => winit::event::Event::DeviceEvent { device_id, event },
Event::UserEvent(x) => winit::event::Event::UserEvent(x),
Event::Suspended => winit::event::Event::Suspended,
Event::Resumed => winit::event::Event::Resumed,
Event::MainEventsCleared => winit::event::Event::MainEventsCleared,
Event::RedrawRequested(x) => winit::event::Event::RedrawRequested(x),
Event::RedrawEventsCleared => winit::event::Event::RedrawEventsCleared,
Event::LoopDestroyed => winit::event::Event::LoopDestroyed
}
}
}
#[allow(deprecated)]
impl WindowEvent {
pub fn from(event: winit::event::WindowEvent<'_>) -> (Self, Option<&mut PhysicalSize<u32>>) {
match event {
winit::event::WindowEvent::Resized(x) => (WindowEvent::Resized(x), None),
winit::event::WindowEvent::Moved(x) => (WindowEvent::Moved(x), None),
winit::event::WindowEvent::CloseRequested => (WindowEvent::CloseRequested, None),
winit::event::WindowEvent::Destroyed => (WindowEvent::Destroyed, None),
winit::event::WindowEvent::DroppedFile(x) => (WindowEvent::DroppedFile(x), None),
winit::event::WindowEvent::HoveredFile(x) => (WindowEvent::HoveredFile(x), None),
winit::event::WindowEvent::HoveredFileCancelled => (WindowEvent::HoveredFileCancelled, None),
winit::event::WindowEvent::ReceivedCharacter(x) => (WindowEvent::ReceivedCharacter(x), None),
winit::event::WindowEvent::Focused(x) => (WindowEvent::Focused(x), None),
winit::event::WindowEvent::KeyboardInput { device_id, input, is_synthetic } => (WindowEvent::KeyboardInput { device_id, input, is_synthetic }, None),
winit::event::WindowEvent::ModifiersChanged(x) => (WindowEvent::ModifiersChanged(x), None),
winit::event::WindowEvent::CursorMoved { device_id, position, modifiers } => (WindowEvent::CursorMoved { device_id, position, modifiers }, None),
winit::event::WindowEvent::CursorEntered { device_id } => (WindowEvent::CursorEntered { device_id }, None),
winit::event::WindowEvent::CursorLeft { device_id } => (WindowEvent::CursorLeft { device_id }, None),
winit::event::WindowEvent::MouseWheel { device_id, delta, modifiers, phase } => (WindowEvent::MouseWheel { device_id, delta, modifiers, phase }, None),
winit::event::WindowEvent::MouseInput { device_id, modifiers, state, button } => (WindowEvent::MouseInput { device_id, modifiers, state, button }, None),
winit::event::WindowEvent::TouchpadPressure { device_id, pressure, stage } => (WindowEvent::TouchpadPressure { device_id, pressure, stage }, None),
winit::event::WindowEvent::AxisMotion { device_id, axis, value } => (WindowEvent::AxisMotion { device_id, axis, value }, None),
winit::event::WindowEvent::Touch(x) => (WindowEvent::Touch(x), None),
winit::event::WindowEvent::ScaleFactorChanged { scale_factor, new_inner_size } => (WindowEvent::ScaleFactorChanged { scale_factor, new_inner_size: NewInnerSize(Arc::new(Mutex::new(*new_inner_size))) }, Some(new_inner_size)),
winit::event::WindowEvent::ThemeChanged(x) => (WindowEvent::ThemeChanged(x), None),
}
}
pub fn into(self, physical_size: Option<&mut PhysicalSize<u32>>) -> winit::event::WindowEvent<'_> {
match self {
WindowEvent::Resized(x) => winit::event::WindowEvent::Resized(x),
WindowEvent::Moved(x) => winit::event::WindowEvent::Moved(x),
WindowEvent::CloseRequested => winit::event::WindowEvent::CloseRequested,
WindowEvent::Destroyed => winit::event::WindowEvent::Destroyed,
WindowEvent::DroppedFile(x) => winit::event::WindowEvent::DroppedFile(x),
WindowEvent::HoveredFile(x) => winit::event::WindowEvent::HoveredFile(x),
WindowEvent::HoveredFileCancelled => winit::event::WindowEvent::HoveredFileCancelled,
WindowEvent::ReceivedCharacter(x) => winit::event::WindowEvent::ReceivedCharacter(x),
WindowEvent::Focused(x) => winit::event::WindowEvent::Focused(x),
WindowEvent::KeyboardInput { device_id, input, is_synthetic } => winit::event::WindowEvent::KeyboardInput { device_id, input, is_synthetic },
WindowEvent::ModifiersChanged(x) => winit::event::WindowEvent::ModifiersChanged(x),
WindowEvent::CursorMoved { device_id, position, modifiers } => winit::event::WindowEvent::CursorMoved { device_id, position, modifiers },
WindowEvent::CursorEntered { device_id } => winit::event::WindowEvent::CursorEntered { device_id },
WindowEvent::CursorLeft { device_id } => winit::event::WindowEvent::CursorLeft { device_id },
WindowEvent::MouseWheel { device_id, delta, modifiers, phase } => winit::event::WindowEvent::MouseWheel { device_id, delta, modifiers, phase },
WindowEvent::MouseInput { device_id, modifiers, state, button } => winit::event::WindowEvent::MouseInput { device_id, modifiers, state, button },
WindowEvent::TouchpadPressure { device_id, pressure, stage } => winit::event::WindowEvent::TouchpadPressure { device_id, pressure, stage },
WindowEvent::AxisMotion { device_id, axis, value } => winit::event::WindowEvent::AxisMotion { device_id, axis, value },
WindowEvent::Touch(x) => winit::event::WindowEvent::Touch(x),
WindowEvent::ScaleFactorChanged { scale_factor, new_inner_size } => {
let physical_size = physical_size.unwrap();
if let Ok(new_inner_size) = new_inner_size.lock() {
*physical_size = *new_inner_size;
}
winit::event::WindowEvent::ScaleFactorChanged { scale_factor, new_inner_size: physical_size }
},
WindowEvent::ThemeChanged(x) => winit::event::WindowEvent::ThemeChanged(x)
}
}
}