#![allow(dead_code)]
use std::io;
use std::fmt;
#[cfg(not(any(feature = "winit", feature = "glfw")))]
#[path = "dummy.rs"]
mod backend;
#[cfg(feature = "winit")]
#[path = "winit.rs"]
mod backend;
#[cfg(all(feature = "glfw", not(feature = "winit")))]
#[path = "glfw.rs"]
mod backend;
pub fn init<T>(
title: &str,
w: u32,
h: u32,
hints: &[WindowHint],
) -> io::Result<(backend::Window<T>, backend::Events)> {
backend::init(title, w, h, hints)
}
pub fn run<F, T>(win: backend::Window<T>, events: backend::Events, callback: F) -> T
where
F: 'static + FnMut(&mut backend::Window<T>, WindowEvent) -> ControlFlow<T>,
T: Default,
{
backend::run(win, events, callback)
}
#[derive(Debug, PartialEq, Eq)]
pub enum ControlFlow<T> {
Continue,
Wait,
Exit(T),
}
#[derive(Debug, Copy, Clone)]
pub enum WindowHint {
Resizable(bool),
Visible(bool),
}
#[derive(Clone, Debug, PartialEq)]
pub enum WindowEvent {
Resized(LogicalSize),
Moved(LogicalPosition),
Minimized,
Restored,
CloseRequested,
Destroyed,
ReceivedCharacter(char),
Focused(bool),
KeyboardInput(KeyboardInput),
CursorMoved {
position: LogicalPosition,
},
CursorEntered,
CursorLeft,
MouseInput {
state: InputState,
button: MouseButton,
modifiers: ModifiersState,
},
MouseWheel { delta: LogicalDelta },
RedrawRequested,
Ready,
HiDpiFactorChanged(f64),
Noop,
}
impl WindowEvent {
pub fn is_input(&self) -> bool {
match self {
Self::Resized(_)
| Self::Moved(_)
| Self::Minimized
| Self::Restored
| Self::CloseRequested
| Self::Destroyed
| Self::ReceivedCharacter(_)
| Self::Focused(_)
| Self::KeyboardInput(_)
| Self::CursorMoved { .. }
| Self::CursorEntered
| Self::CursorLeft
| Self::MouseInput { .. }
| Self::HiDpiFactorChanged(_) => true,
_ => false,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct KeyboardInput {
pub state: InputState,
pub key: Option<Key>,
pub modifiers: ModifiersState,
}
#[derive(Debug, Hash, PartialEq, Eq, Clone, Copy)]
pub enum InputState {
Pressed,
Released,
Repeated,
}
#[derive(Debug, Hash, PartialEq, Eq, Clone, Copy)]
pub enum MouseButton {
Left,
Right,
Middle,
Other(u8),
}
#[derive(Debug, Hash, Ord, PartialOrd, PartialEq, Eq, Clone, Copy)]
#[repr(u32)]
#[rustfmt::skip]
pub enum Key {
Num1, Num2, Num3, Num4, Num5, Num6, Num7, Num8, Num9, Num0,
A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z,
Left, Up, Right, Down,
Backspace, Return, Space, Tab,
Escape, Insert, Home, Delete, End, PageDown, PageUp,
Apostrophe, Grave, Caret, Comma, Period, Colon, Semicolon,
LBracket, RBracket,
Slash, Backslash,
Alt, Control, Shift,
Equal, Minus,
Unknown,
}
impl From<char> for Key {
#[rustfmt::skip]
fn from(c: char) -> Self {
match c {
'0' => Key::Num0, '1' => Key::Num1, '2' => Key::Num2,
'3' => Key::Num3, '4' => Key::Num4, '5' => Key::Num5,
'6' => Key::Num6, '7' => Key::Num7, '8' => Key::Num8,
'9' => Key::Num9,
'a' => Key::A, 'b' => Key::B, 'c' => Key::C, 'd' => Key::D,
'e' => Key::E, 'f' => Key::F, 'g' => Key::G, 'h' => Key::H,
'i' => Key::I, 'j' => Key::J, 'k' => Key::K, 'l' => Key::L,
'm' => Key::M, 'n' => Key::N, 'o' => Key::O, 'p' => Key::P,
'q' => Key::Q, 'r' => Key::R, 's' => Key::S, 't' => Key::T,
'u' => Key::U, 'v' => Key::V, 'w' => Key::W, 'x' => Key::X,
'y' => Key::Y, 'z' => Key::Z,
'/' => Key::Slash, '[' => Key::LBracket, ']' => Key::RBracket,
'`' => Key::Grave, ',' => Key::Comma, '.' => Key::Period,
'=' => Key::Equal, '-' => Key::Minus, '\'' => Key::Apostrophe,
';' => Key::Semicolon, ':' => Key::Colon, ' ' => Key::Space,
'\\' => Key::Backslash,
_ => Key::Unknown,
}
}
}
impl fmt::Display for Key {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Key::A => "a".fmt(f),
Key::B => "b".fmt(f),
Key::C => "c".fmt(f),
Key::D => "d".fmt(f),
Key::E => "e".fmt(f),
Key::F => "f".fmt(f),
Key::G => "g".fmt(f),
Key::H => "h".fmt(f),
Key::I => "i".fmt(f),
Key::J => "j".fmt(f),
Key::K => "k".fmt(f),
Key::L => "l".fmt(f),
Key::M => "m".fmt(f),
Key::N => "n".fmt(f),
Key::O => "o".fmt(f),
Key::P => "p".fmt(f),
Key::Q => "q".fmt(f),
Key::R => "r".fmt(f),
Key::S => "s".fmt(f),
Key::T => "t".fmt(f),
Key::U => "u".fmt(f),
Key::V => "v".fmt(f),
Key::W => "w".fmt(f),
Key::X => "x".fmt(f),
Key::Y => "y".fmt(f),
Key::Z => "z".fmt(f),
Key::Num0 => "0".fmt(f),
Key::Num1 => "1".fmt(f),
Key::Num2 => "2".fmt(f),
Key::Num3 => "3".fmt(f),
Key::Num4 => "4".fmt(f),
Key::Num5 => "5".fmt(f),
Key::Num6 => "6".fmt(f),
Key::Num7 => "7".fmt(f),
Key::Num8 => "8".fmt(f),
Key::Num9 => "9".fmt(f),
Key::LBracket => "[".fmt(f),
Key::RBracket => "]".fmt(f),
Key::Comma => ",".fmt(f),
Key::Period => ".".fmt(f),
Key::Slash => "/".fmt(f),
Key::Backslash => "\\".fmt(f),
Key::Apostrophe => "'".fmt(f),
Key::Control => "<ctrl>".fmt(f),
Key::Shift => "<shift>".fmt(f),
Key::Alt => "<alt>".fmt(f),
Key::Up => "<up>".fmt(f),
Key::Down => "<down>".fmt(f),
Key::Left => "<left>".fmt(f),
Key::Right => "<right>".fmt(f),
Key::Return => "<return>".fmt(f),
Key::Backspace => "<backspace>".fmt(f),
Key::Space => "<space>".fmt(f),
Key::Tab => "<tab>".fmt(f),
Key::Escape => "<esc>".fmt(f),
Key::Insert => "<insert>".fmt(f),
Key::Delete => "<delete>".fmt(f),
Key::Home => "<home>".fmt(f),
Key::PageUp => "<pgup>".fmt(f),
Key::PageDown => "<pgdown>".fmt(f),
Key::Grave => "`".fmt(f),
Key::Caret => "^".fmt(f),
Key::End => "<end>".fmt(f),
Key::Colon => ":".fmt(f),
Key::Semicolon => ";".fmt(f),
Key::Equal => "=".fmt(f),
Key::Minus => "-".fmt(f),
_ => "???".fmt(f),
}
}
}
#[derive(Default, Debug, Hash, PartialEq, Eq, Clone, Copy)]
pub struct ModifiersState {
pub shift: bool,
pub ctrl: bool,
pub alt: bool,
pub meta: bool,
}
impl fmt::Display for ModifiersState {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut s = String::new();
if self.ctrl {
s.push_str("<ctrl>");
}
if self.alt {
s.push_str("<alt>");
}
if self.meta {
s.push_str("<meta>");
}
if self.shift {
s.push_str("<shift>");
}
s.fmt(f)
}
}
#[derive(Debug, Copy, Clone, PartialEq)]
pub struct LogicalDelta {
pub x: f64,
pub y: f64,
}
#[derive(Debug, Copy, Clone, PartialEq)]
pub struct LogicalPosition {
pub x: f64,
pub y: f64,
}
impl LogicalPosition {
pub fn new(x: f64, y: f64) -> Self {
LogicalPosition { x, y }
}
pub fn from_physical<T: Into<PhysicalPosition>>(physical: T, dpi_factor: f64) -> Self {
physical.into().to_logical(dpi_factor)
}
pub fn to_physical(&self, dpi_factor: f64) -> PhysicalPosition {
let x = self.x * dpi_factor;
let y = self.y * dpi_factor;
PhysicalPosition::new(x, y)
}
}
#[derive(Debug, Copy, Clone, PartialEq)]
pub struct PhysicalPosition {
pub x: f64,
pub y: f64,
}
impl PhysicalPosition {
pub fn new(x: f64, y: f64) -> Self {
PhysicalPosition { x, y }
}
pub fn from_logical<T: Into<LogicalPosition>>(logical: T, dpi_factor: f64) -> Self {
logical.into().to_physical(dpi_factor)
}
pub fn to_logical(&self, dpi_factor: f64) -> LogicalPosition {
let x = self.x / dpi_factor;
let y = self.y / dpi_factor;
LogicalPosition::new(x, y)
}
}
#[derive(Debug, Copy, Clone, PartialEq)]
pub struct LogicalSize {
pub width: f64,
pub height: f64,
}
impl LogicalSize {
pub const fn new(width: f64, height: f64) -> Self {
LogicalSize { width, height }
}
pub fn from_physical<T: Into<PhysicalSize>>(physical: T, dpi_factor: f64) -> Self {
physical.into().to_logical(dpi_factor)
}
pub fn to_physical(&self, dpi_factor: f64) -> PhysicalSize {
let width = self.width * dpi_factor;
let height = self.height * dpi_factor;
PhysicalSize::new(width, height)
}
pub fn is_zero(&self) -> bool {
self.width < 1. || self.height < 1.
}
}
impl From<(u32, u32)> for LogicalSize {
fn from((width, height): (u32, u32)) -> Self {
Self::new(width as f64, height as f64)
}
}
impl Into<(u32, u32)> for LogicalSize {
fn into(self) -> (u32, u32) {
(self.width.round() as _, self.height.round() as _)
}
}
#[derive(Debug, Copy, Clone, PartialEq)]
pub struct PhysicalSize {
pub width: f64,
pub height: f64,
}
impl PhysicalSize {
pub fn new(width: f64, height: f64) -> Self {
PhysicalSize { width, height }
}
pub fn from_logical<T: Into<LogicalSize>>(logical: T, dpi_factor: f64) -> Self {
logical.into().to_physical(dpi_factor)
}
pub fn to_logical(&self, dpi_factor: f64) -> LogicalSize {
let width = self.width / dpi_factor;
let height = self.height / dpi_factor;
LogicalSize::new(width, height)
}
}
impl From<(u32, u32)> for PhysicalSize {
fn from((width, height): (u32, u32)) -> Self {
Self::new(width as f64, height as f64)
}
}
impl Into<(u32, u32)> for PhysicalSize {
fn into(self) -> (u32, u32) {
(self.width.round() as _, self.height.round() as _)
}
}